r multiple graphs on a single jpeg - r

I have run into the following problem and I would appreciate if someone could give me some input.
I would like to export multiple figures to a single jpeg file. I first create a graphics lattice and then I export. My main issue is that it works with the pdf and not the jpeg. Any ideas?
Thank you
#set the windows of the frames
par(mfcol=c(3,2))
#create the jpeg file
jpeg(filename=names(a1),".jpg",sep=""),
quality=100,
width=1024,
height=768)
#plot 1
plot(a1,b1)
#plot 2
plot(a1,b2)
#plot 3
plot(a1,b3)
#plot 4
plot(a2, c1)
#plot 5
plot(a2, c2)
#plot 6
plot(a2, c3)
#dev.off shuts down the specified (by default the current) graphical device
#here it passes the picture to the file
dev.off()

It is not clear whether you want multiple 1024x768 images in a single jpeg file - which doesn't make sense - are whether you want a single jpeg image containing the 6 plots.
As I said, JPEGs are not a multi-page format, unlike a PDF. Hence you can get R to export to multiple JPEG files but not have all the separate figures in one JPEG.
R's devices allow for wildcards in the filenames, so if you want the six plots exported to files foo001.jpeg, foo002.jpeg, foo00x.jpeg then you can use the following
jpeg(filename = "foo%03d.jpeg", ....)
.... # plotting commands here
dev.off()
What happens if you do multiple plots without the wildcard/placeholder is document in say ?jpeg:
If you plot more than one page on one of these devices and do not
include something like ‘%d’ for the sequence number in ‘file’, the
file will contain the last page plotted.
Devices that handle multiple pages because the underlying file format allows it can take multiple plots into the single file as there is makes sense, e.g. pdf() and postscript(). Those devices have argument onefile which can be used to indicate if multiple plots in a single file are required.
However, the par(mfcol=c(3,2)) makes me think you want a 3x2 set of plots in the same device region. That is allowed, but you need to call par() after you open the jpeg() device, not before. What your code, as shown, does is split the active device into 3x2 plotting regions and then opens a new device which picks up the default parameters, not the ones you set on the device active before you called jpeg(). This is illustrated below:
> plot(1:10)
> dev.cur()
X11cairo
2
> op <- par(mfrow = c(3,2))
> jpeg("~/foo.jpg")
> par("mfrow")
[1] 1 1
> dev.off()
X11cairo
2
> par("mfrow")
[1] 3 2
Hence you want perhaps wanted something like:
jpeg(filename=names(a1),".jpg",sep=""), quality=100,
width=1024, height=768)
op <- par(mfcol=c(3,2))
#plot 1
plot(a1,b1)
#plot 2
plot(a1,b2)
#plot 3
plot(a1,b3)
#plot 4
plot(a2, c1)
#plot 5
plot(a2, c2)
#plot 6
plot(a2, c3)
par(op)
dev.off()
?

The corrected code
#data
a1<-seq(1,20,by=1)
b1<-seq(31,50,by=1)
b2<-seq(51,70,by=1)
b3<-seq(71,90,by=1)
#create the jpeg file
jpeg(filename="a.jpg",
quality=100,
width=1024,
height=768)
#set the create the frames
par(mfcol=c(3,1))
#plot the graphs
plot(a1,b1)
plot(a1,b2)
plot(a1,b3)
#par(op)
#dev.off shuts down the specified (by default the current) graphical device
#here it passes the picture to the file
dev.off()

Related

How can I View the output of this animation code in Rstudio

This R code is to create an animated plot, I have run it and it did run but I have not been able to view it. it is said to save it output on pdf file though I saw the file but unable to open it. I got the code at How do I transfer output of animation R package on a beamer frame
because I want to learn how to input R animated plot on latex thus I was given this as an example. can you show me how I can view its output either on Rstudio or where the code saves it to? If you mean that the output can be viewed on pdf that is originally saved to, show me how? I am using Acrobat Reade Dc.
brownianMotion <- function(n=10,xlim=c(-20,20),ylim=c(-20,20),steps=50)
{
x=rnorm(n)
y=rnorm(n)
for (i in 1:steps) {
plot(x,y,xlim = xlim,ylim = ylim)
text(x,y)
# iterate over particles
for(k in 1:n){
walk=rnorm(2); # random move of particle
x[k]=x[k]+walk[1] # new position
y[k]=y[k]+walk[2]
# simple model for preventing a particle from moving past the limits
if(x[k]<xlim[1]) x[k]=xlim[1]
if(x[k]>xlim[2]) x[k]=xlim[2]
if(y[k]<ylim[1]) y[k]=ylim[1]
if(y[k]>ylim[2]) y[k]=ylim[2]
}
}
}
pdf("frames.pdf") # output device and file name
par(xaxs="i", yaxs="i", pty="s") # square plot region
par(mai=c(0.9,0.9,0.2,0.2)) # plot margins
brownianMotion(n=20, steps=400) # 20 particles, 400 time steps
There are two things here :
you need to add dev.off() after plotting so that the current plot is saved to the output device
the loop over step is rewriting the same filename for each plot, so that you end-up in having only the last frame in frames.pdf. Following this tutorial, you should rather write separate pdf files to an output folder, then animate them within LaTeX.
brownianMotion <- function(n=10,xlim=c(-20,20),ylim=c(-20,20),steps=50){
x=rnorm(n)
y=rnorm(n)
for (i in 1:steps) {
pdf(paste0("out/frames", i, ".pdf")) # save frames{i}.pdf to 'out' folder
plot(x,y,xlim = xlim,ylim = ylim)
text(x,y)
dev.off() # Adding dev.off()
...
}
}
par(xaxs="i", yaxs="i", pty="s") # square plot region
par(mai=c(0.9,0.9,0.2,0.2)) # plot margins
if (!dir.exists("out")) dir.create("out") # create 'out' folder if it doesn't exist
brownianMotion(n=20, steps=4) # 20 particles, 4 steps
The out folder will be located where your working directory is (use getwd() to see it).

Saving two ggplots in grid.arrange to eps file format

I am working in RStudio and have two ggplots, call them plot1 and plot2. I would like to arrange them one above the other and save into eps format. I have read the following posts on the topic:
Export a graph to .eps file with R
Saving grid.arrange() plot to file
Side-by-side plots with ggplot2
I have tried multiple methods which I list below, all of which have failed. Most revolve around using gridarrange.
1) My initial method was to run:
setEPS()
postscript("Figure1.eps",width=11.5,height=16)
grid.arrange(plot1,plot2,nrow=2,heights=c(9.5/20,10.5/20))
dev.off()
Similar to link 1 but with grid.arrange. There are no errors in R and an EPS file appears in my directory, however the filesize is small and I cannot open it in a file viewer, it appears to be corrupted for some reason.
2) My second attempt used ggsave:
grid.arrange(plot1,plot2,nrow=2,heights=c(9.5/20,10.5/20))
ggsave("Figure1.eps", p)
This saves only the second plot. Then try suggestions from comments from link 2:
The code
p <- arrangeGrob(plot1,plot2,nrow=2,heights=c(9.5/20,10.5/20))
grid.draw(p) # interactive device
ggsave("Figure1.eps", p)
gives output: Error in ggsave("saving.eps", p) : plot should be a ggplot2 plot
The code
grid.arrange(plot1,plot2,nrow=2,heights=c(9.5/20,10.5/20))
p<-arrangeGrob(plot1,plot2,nrow=2,heights=c(9.5/20,10.5/20))
ggsave("Figure1.eps", p)
gives output: Error in ggsave("saving.eps", p) : plot should be a ggplot2 plot
The code
grid.arrange(plot1,plot2,nrow=2,heights=c(9.5/20,10.5/20))
ggsave <- ggplot2::ggsave; body(ggsave) <- body(ggplot2::ggsave)[-2]
p<-arrangeGrob(plot1,plot2,nrow=2,heights=c(9.5/20,10.5/20))
ggsave("Figure1.eps", p)
gives output:
Saving 8.28 x 9.07 in image
TableGrob (2 x 1) "arrange": 2 grobs
z cells name grob
1 1 (1-1,1-1) arrange gtable[layout]
2 2 (2-2,1-1) arrange gtable[layout]
In this final case, a file appears in the directory but it is small and cannot be opened.
3) My final attempt is just to use the command
png("Figure1.eps",height=11.5,width=16,units="cm",res=600)
grid.arrange(plot1,plot2,nrow=2,heights=c(9.5/20,10.5/20))
dev.off()
This produces a 'eps' file and is of a large size, and can be opened, however I am unsure if to trust it. Why would the png command be able to create an eps file? I have a feeling it's just a png file but masked as an eps somehow if that is possible. Is there a way to check the files format?
EDIT: Code to create plots for which the above code can be ran.
data1<-data.frame(a=c(1,2,3,4,0.5,1,1.5,2,0.5,1,3,4),b=c(1,2,3,4,1,2,3,4,1,2,3,4),
c=c('graph1','graph1','graph1','graph1','graph2','graph2','graph2','graph2','graph3','graph3','graph3','graph3'))
data2<-data.frame(a=c(10,20,25,40,13,14,25,37,2,20,34,35),b=c(1,2,3,4,1,2,3,4,1,2,3,4),
c=c('graph1','graph1','graph1','graph1','graph2','graph2','graph2','graph2','graph3','graph3','graph3','graph3'))
plot1<-ggplot(data1, aes(x=b,y=a)) +
geom_line() +
geom_point(size=2.5) +
facet_wrap(~c, scales="fix") +
scale_x_continuous(limits=c(1,4),labels=c("Zero","Low","Med","High")) +
ylab("ylab1") +
coord_cartesian(ylim=c(0,4)) +
theme(legend.position="none",axis.title.x=element_blank(), panel.margin.x=unit(1.1, "lines"))
plot2<-ggplot(data2, aes(x=b,y=a)) +
geom_line() +
geom_point(size=2.5) +
facet_wrap(~c, scales="fix") +
scale_x_continuous(limits=c(1,4),labels=c("Zero","Low","Med","High")) +
coord_cartesian(ylim=c(0,40)) +
xlab("level of correlation") +
ylab("ylab2") +
theme(legend.position="none",axis.title.x=element_blank(), panel.margin.x=unit(1.1, "lines"))
EDIT: I have also now realised that
setEPS()
postscript("TestFig3.eps")
plot1
dev.off()
which should just simply create an eps file (no grid.arrange involved) also does not work. A file is created and no error message in R, but it is corrupted in some way.
Ideally I would like an
eps()
grid.arrange()
dev.off()
but ?eps provides no packages.
I realise there is already quite a lot of chat about this, however I have not been able to source a solution from it all.

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()

plot got cut off after saving to file

My fig has a large legend outside the plot. 6 lines with long description When I save it, the legend doesn't show up. I adjusted par, but it still doesn't work.
legend("topright", inset=c(-0.6,0),xpd=TRUE,cex=0.8,
+legend=c("A_all peaks","B_ from all peaks","C_from all peaks","A_from unique peaks",
+"B_from unique peaks","C_from unique peaks",
+"A_from overlap peaks","B_from overlap peaks","C_from overlap peaks"),
+col=c("green","red","blue","lightgreen","pink","lightblue","darkgreen","darkred","steelblue"),
+pch=c(20,20,20,20,20,20,20,20,20),bty="n")
> par()$oma
[1] 2 2 2 2
> par()$mar
[1] 5.1 4.1 4.1 8.0
When save it with long width(tried 800,1000 pixel), no legend showed. But when as as short width(), part of legend shows. This is really confused me.first graph is 500*333, second graph is 500*800.
Not sure how you're saving the plot to file, but my usual routine is to make a pretty plot in R by the usual means:
plot(blah,blah,blah)
legend(blah,blah,blah)
and then once I'm happy with the appearance of the figure the R console, I use pdf() or one of it's cousins(jpeg(),tiff(), etc.) to save it to file, making sure to set the width and height parameters like so:
# set up plotting device
pdf( {{FileName}},
width = par('din')[1],
height = par('din')[2])
plot(blah,blah,blah)
legend(blah,blah,blah)
# disconnect the plotting device
dev.off()
Save it using png() or tiff():
tiff("filename",
<code for plot>,
height=5,width=7)
dev.off()
After plotting, try
% your code…
dev.copy(pdf, 'yourfile.pdf')
dev.off()
From https://statistics.berkeley.edu/computing/saving-plots-r

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

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)

Resources