fast way to read in png, add grid & coords, and output - r

I have a lot of png files of a floor plan (mapping) layout that I want to:
read into R
Add grid lines
Add coordinates per cell in grid
Output
There are 1000 of these files so I'm looking for a speedy method. What would be a fast way to accomplish this task. These don't need to be publication quality as I'm looking for certain behavior clusters within cells and want recording the coordinated for these events for each of the 100 frames (pngs).
Here is a MWE that produces 10 png files:
x <- y <- seq(-4*pi, 4*pi, len = 27)
r <- sqrt(outer(x^2, y^2, "+"))
dir.create("delete_me")
wd <- getwd()
setwd("delete_me")
lapply(1:10, function(x){
png(sprintf("file_%s.png", x))
image(z = z <- cos(r^2)*exp(-r/x))
dev.off()
})
setwd(wd)
The final output will look like this for each png (with all the coords filled in).
I assume grid will be the way to create the gridlines quickly but am not sure about reading the png in quickly or plotting the coordinates (assume we'll use a 10 x 10 grid on each png).

How about using ggplot() and annotation_custom() to plot the image across the entire plot area, then manually overplot the grid lines.
(In the image, I trimmed the excess whitespace and axis from the png file in advance)
# pre-req libraries
require(ggplot2)
require(grid) # rasterGrob function
require(png) # to read the PNG file
width<-10
height<-10
# generate the points and labels for the grid
points<-data.frame(expand.grid(w=1:width,h=1:height))
points$labs<-paste0("(",points$w,",",points$h,")")
points$x<-points$w-0.5 # center
points$y<-points$h-0.5
# make the gridline co-ordinates
gridx<-data.frame(x=0:width,xend=0:width,y=rep(0,width+1),yend=rep(height,width+1))
gridy<-data.frame(x=rep(0,height+1),xend=rep(width,height+1),y=0:height,yend=0:height)
grids<-rbind(gridx,gridy)
# function to plot using ggplot with annotation_custom for the image
plotgrid<-function(file){
g<-ggplot(points)+theme_bw()+
annotation_custom(rasterGrob(readPNG(file),0,0,1,1,just=c("left","bottom")),0,width,0,height)+
geom_text(aes(x=x,y=y,label=labs))+
geom_segment(aes(x=x,xend=xend,y=y,yend=yend),data=grids) +
coord_cartesian(c(0,width),c(0,height))
return(g)
}
# run the function for each file in the folder
setwd("delete_me")
lapply(list.files(),function(x)plotgrid(x))
setwd(wd)

Related

How can i use "rasterVis" package to overlay two raster and display well?

I want to overlay two raster objects.
I asked the question(Raster overlay visualization in rasterVis package: How the Significant raster images are represented as point marks?).
I refer to the #thiagoveloso'answer from this(Adding stippling to image/contour plot).
But the display is not what I wanted. It's not obvious and beautiful. If I try to change the shape or size of the mark, it will take a long long long time to draw or become weird.
Here is my code:
library(raster)
library(rasterVis)
rm(list = ls())
MK<-raster("C:/e_Zs——trend.tif")
### MK<1.96 set value to NA
fun <- function(x) { x[x<3] <- NA; return(x) }
MK<-calc(MK,fun = fun)
## load trend
Trend<- raster("C:/e_slope_trend.tif")
# And this is the key step:
# Converting the "mask" raster to spatial points
r.mask <- rasterToPoints(MK, spatial=TRUE)
plot(r.mask,cex=0.01)
# Plot
levelplot(Trend, margin=NA,par.settings=RdBuTheme) +
latticeExtra::layer(sp.points(r.mask, pch=100, cex=0.1, alpha=0.3,col="Black"))
I want to draw a fig,like:
And the fig like:
If i change the cex=0.5,it will lke:
If I change the shape of the mark, it will do so long... So. get any idea?

Plot multiple ggplot2 on same page

I have a working loop which generates and can save individual plots from each file saved in a directory.
I want to plot all of the returned plots in a single file as a 2x2 grid over multiple pages but cannot do this.
I have tried to save the plot objects in a list
pltList <- list()
pltList[]
for (f in 1:length(files)){
plot_object <- ggplot2(...) #make ggplot2 plot
print(plot_object)
pltList[[f]] <- plot_object #save ggplot2 plot in list
}
jpeg(filename.jpg)
par(mfrow=c(2,2)) #to generate 2x2 plot per page
print(pltList[[1]])
print(pltList[[2]])
...
print(pltList[[f]])
dev.off()
The problem is that the resulting saved .jpg file only contains the last plot and not a 2x2 grid of all plots over many pages which is what I want.
EDIT
My first problem is how to save each plot from the loop in the list - how can I view the saved objects from the list to make sure they have been saved correctly?
When I do print(pltList[1]), the resulting output is:
function (x, y, ...)
UseMethod("plot")
<bytecode: 0x0000000010f43b78>
<environment: namespace:graphics>
rather than the actual plot. It seems that the plots are not being saved in the list as expected. How can I correct for this?
Hopefully, once this is fixed, your plotting suggestions will work.
I did recently the same. I used grid.arrange().
library(ggplot2)
library(gridExtra)
library(grid)
p1<-ggplot()+geom_line(aes(x=1:10,y=1:10))
p2<-ggplot()+geom_line(aes(x=1:10,y=1:10))
p3<-ggplot()+geom_line(aes(x=1:10,y=1:10))
p4<-ggplot()+geom_line(aes(x=1:10,y=1:10))
grid.arrange(p1,p2,p3,p4, ncol=1, top=textGrob("Multiple Plots", gp=gpar(fontsize=12, font = 2)))
Assuming you need a PDF output where every page has multiple plots plotted as one, e.g.: if there are 12 plots then 4 plots per page.
Try this example:
library(ggplot2)
library(cowplot)
# list of 12 dummy plots, only title is changing.
pltList <- lapply(1:12, function(i){
ggplot(mtcars,aes(mpg,cyl)) +
geom_point() +
ggtitle(paste("Title",i))})
# outputs 3 jpeg files with 4 plots each.
for(i in seq(1,12,4))
ggsave(paste0("Temp",i,".jpeg"),
plot_grid(pltList[[i]],
pltList[[i+1]],
pltList[[i+2]],
pltList[[i+3]],nrow = 2))
# or we can output into 1 PDF with 3 pages using print
pdf("TempPDF.pdf")
for(i in seq(1,12,4))
print(plot_grid(pltList[[i]],
pltList[[i+1]],
pltList[[i+2]],
pltList[[i+3]],nrow = 2))
dev.off()
EDIT:
Another way using gridExtra, as suggested by #user20650:
library(gridExtra)
#output as PDF
pdf("multipage.pdf")
#use gridExtra to put plots together
marrangeGrob(pltList, nrow=2, ncol=2)
dev.off()

How to plot and animate coordinates (latitude/longitude) data in R?

I have 10 lat and long points. With the code below, I can plot the coordinates, draw arrows in the order of their sequence and out-put a gif file that shows navigation order.
So far I was able to do this only with plot {graphics} function. because arrow {graphics} and saveGIF{animation} only seems to work with the plot function. I am wondering if its possible to this a more appropriate library such as ggmap (edit: I had mistakenly said ggplot), googleVis and etc.
library(graphics)
library(animation)
lat <- c(34.083398,34.072467,34.030237,34.597334,34.587142,34.488386,33.443484,33.946902,33.062739,32.273711,32.272611)
lon <- c(-107.907107,-106.893156,-107.971542,-105.225107,-105.13397,-103.196355,-104.52479,-103.655698,-106.0156,-107.71744,-107.713977)
coords = data.frame(lat,lon)
x <- coords$lat ; y <- coords$lon
s <- seq(length(x)-1) # one shorter than data
saveGIF({
for(s in 1:length(x)){
plot(x,y)
arrows(x[s], y[s], x[s+1], y[s+1], col = 1:s)
}
})
Yes, just remember to wrap your ggplot calls in print so they produce output. Toy example:
data=data.frame(i=1:100,x=runif(100),y=runif(100))
saveGIF({for(i in 2:100){print(ggplot(data[1:i,],aes(x=x,y=y))+geom_point())}})
Just write your code to produce each frame with ggplot2 functions and wrap in print. What did you try?

Labelling the plots with images on graph in ggplot2

So I have this R script that can produce a scatter plot with labels of each point. Sth like this:
img1<-"http://blog.gettyimages.com/wp-content/uploads/2013/01/Siberian-Tiger-Running-Through-Snow-Tom-Brakefield-Getty-Images-200353826-001-628x419.jpg"
img2<-"http://blog.gettyimages.com/wp-content/uploads/2013/01/Hurricane-Sandy-Andrew-Burton-Getty-Images-154986556.jpg"
imgdata<-data.frame(c(img1,img2,img1,img2,img1,img2,img1,img2,img1,img2))
colnames(imgdata)<-"images"
txtdata<-data.frame(c("A","B","C","D","E","F","G","H","I","J"))
plotdata<-data.frame(seq(1:10),seq(11:20),txtdata,imgdata)
colnames(plotdata)<-c("var1","var2","texts","images")
ggplot(data=plotdata, aes(plotdata[,1],plotdata[,2])) +
geom_point(data=plotdata, aes(plotdata[,1],plotdata[,2])) +
geom_text(aes(label=plotdata$points,size=2, hjust=2))
This gives a scatter plot, where each point is labelled as "A", "B", "C"... etc.
What I want to do is almost the same, except instead of texts, I want to label each point with the image that are in the links of a vector or data frame (in this case in "imgdata"). Note that I selected these images just as examples; I have much more of them, so I can't manually download them.
You can use annotation_custom, but it will be a lot of work because each image has to be rendered as a raster object and its location specified. I saved the images as png files to create this example.
library(ggplot2)
library(png)
library(grid)
img1 <- readPNG("c:/test/img1.png")
g1<- rasterGrob(img1, interpolate=TRUE)
img2 <- readPNG("c:/test/img2.png")
g2<- rasterGrob(img2, interpolate=TRUE)
plotdata<-data.frame(seq(1:2),seq(11:12))
ggplot(data=plotdata) + scale_y_continuous(limits=c(0,4))+ scale_x_continuous(limits=c(0,4))+
geom_point(data=plotdata, aes(plotdata[,1],plotdata[,2])) +
annotation_custom(g1,xmin=1, xmax=1.5,ymin=1, ymax=1.5)+
annotation_custom(g2,xmin=2, xmax=2.5,ymin=2, ymax=2.5)

Clearing plotted points in R

I am trying to use the animation package to generate an "evolving" plot of points on a map. The map is generated from shapefiles (from the readShapeSpatial/readShapeLines functions).
The problem is when it's plotted in a for loop, the result is additive, whereas the ideal result is to have it evolve.
Are there ways of using par() that I am missing?
My question is: is there a way to clear just the points ploted from the points function
and not clearing the entire figure thus not having to regraph the shapefiles?
in case someone wants to see code:
# plotting underlying map
newyork <- readShapeSpatial('nycpolygon.shp')
routes <- readShapeLines('nyc.shp')
par(bg="grey25")
plot(newyork, lwd=2, col ="lightgray")
plot(routes,add=TRUE,lwd=0.1,col="lightslategrey")
# plotting points and save to GIF
ani.options(interval=.05)
saveGIF({
par(bg="grey25")
# Begin loop
for (i in 13:44){
infile <-paste("Week",i,".csv",sep='')
mydata <-read.csv(file = infile, header = TRUE, sep=",")
plotvar <- Var$Para
nclr <- 4
plotclr <-brewer.pal(nclr,"RdPu")
class<- classIntervals(plotvar,nclr,style = "pretty")
colcode <- findColours(class,plotclr)
points(Var$Lon,Var$Lat,col=colcode)
}
})
If you can accept a residual shadow or halo of ink, you can over-plot with color ="white" or == to your background choices. We cannot access your shape file but you can try it out by adding this line:
points(Var$Lon, Var$Lat, col="grey25")
It may leave gaps in other previously plotted figures or boundaries, because it's definitely not object-oriented. The lattice and ggplot2 graphics models are more object oriented, so if you want to post a reproducible example, that might be an alternate path to "moving" forward. I seem to remember that the rgl package has animation options in its repetoire.

Resources