I would like to make a composite graphic which is 3 panels wide by 8 panels tall. Inside each of the panel would be a graphic that takes multiple R commands to create, like the 1st 3 graphics might be
#1
plot(c(2:20), c(2:20), ylab="", xlab="", axes=FALSE)
par(new=TRUE)
plot(c(1:18, c(1:18), xact="n"), type="l", xlab="", ylab="")
#2
plot(c(2:20), c(2:20), ylab="", xlab="", axes=FALSE)
par(new=TRUE)
plot(c(1:18, c(1:18), xact="n"), type="l", xlab="", ylab="", col=2)
#3
plot(c(2:20), c(2:20), ylab="", xlab="", axes=FALSE, col=3)
par(new=TRUE)
plot(c(1:18, c(1:18), xact="n"), type="l", xlab="", ylab="")
and then I want to use a command like this to display those 3 side by side:
grid.arrange(plot1, plot2, plot3)
I don't understand how to save #1, #2, and #3 each to be plot1, plot2 and plot3. Examples of how to save plots all seem to be based on a single plot command, not multiple commands to make the plot. The help page says grob but doesn't explain what an acceptable grob might be, or how to make it. Should I screenshot each of those and save it as a jpeg file?
thanks for any help.
You can set par(mfrow = c(8, 3)). This will draw each plot in a single panel of an 8 x 3 grid. And will only move on to draw the next plot when plot.new is (implicitly) called.
par(mfrow = c(8, 3))
par(mar = c(0.5, 0.5, 0.5, 0.5)) # Otherwise margins are too large for 24 plots
for(i in 1:24) {
plot(c(2:20), c(2:20), ylab = "", xlab = "", axes = FALSE, col = 3)
par(new = TRUE)
plot(c(1:18), c(1:18), xaxt = "n", type = "l", xlab = "", ylab = "")
}
Update & solution:
Don't use grid.arrange(), don't use jpeg(), recordplot(), pdf() or ggplot...
The below code worked by adding features to the original plots. Then it helps (within RStudio) exporting results as high resolution PNG. I can label the row/columns separately well enough in MS Word.
par(mfrow=c(1,3))
#1
plot1=plot(c(2:20), c(2:20), ylab="", xlab="", axes=FALSE)
par(new=TRUE)
plot1= plot1 + plot(c(1:18, c(1:18), xact="n"), type="l", xlab="", ylab="")
#2
plot2 = plot(c(2:20), c(2:20), ylab="", xlab="", axes=FALSE)
par(new=TRUE)
plot2 = plot2 + plot(c(1:18, c(1:18), xact="n"), type="l", xlab="", ylab="", col=2)
#3
plot3 = plot(c(2:20), c(2:20), ylab="", xlab="", axes=FALSE, col=3)
par(new=TRUE)
plot3 = plot3 + plot(c(1:18, c(1:18), xact="n"), type="l", xlab="", ylab="")
Related
I'm trying to make a boxplot with custom axis labels, but I can't seem to add an x-axis to the plot.
For example:
test <- data.frame(year=as.integer(rep(1963:2014, each=10)),
response=rnorm(520))
boxplot(response~year, data=test, ylim=c(-3,3), xlab="", ylab="",
range=0, xaxt="n", yaxt="n")
responselabs <- as.numeric(c(-3:3, by=1))
yearlabs <- as.integer(seq(1965,2015, by=5))
axis(2, at=responselabs, tck=0.03, las=1)
axis(1, at=yearlabs, tck=0.03)
returns the boxplot, but no x-axis labels:
Trying to hack it the other way by making an empty plot first, I can get the axes, but it won't add the boxplot:
plot(NA, ylim=c(-3, 3), xlim=c(1962, 2015), xaxt="n", yaxt="n", ylab="", xlab="")
axis(2, at=responselabs, tck=0.03, las=1)
axis(1, at=yearlabs, tck=0.03)
boxplot(response~year, data=test, ylim=c(-3,3), xlab="", ylab="",
range=0, xaxt="n", yaxt="n", add=T)
What's going on here?
I think what's happening is that boxplot converts year to a factor. We can get around this by using the labels argument in axis:
boxplot(response~year, data=test, ylim=c(-3,3), xlab="", ylab="",
range=0, xaxt="n", yaxt="n")
responselabs <- as.numeric(c(-3:3, by=1))
yearlabs <- as.integer(seq(1965,2015, by=5))
axis(2, at=responselabs, tck=0.03, las=1)
axis(1, at = yearlabs - 1962, labels = yearlabs)
Why not use ggplot2?
library(ggplot2)
p<-ggplot(test,aes(x=year,y=response,group=year))+
geom_boxplot()+
scale_x_continuous(breaks=round(seq(min(test$year),max(test$year),by=5),1))
If you want to be rounded to the nearest 5 then the code is fairly easy to adjust in the scale_x_continuous() argument.
p<-ggplot(test,aes(x=year,y=response,group=year))+
geom_boxplot()+
scale_x_continuous(breaks = round(seq(round(min(test$year)/5,0)*5,round(max(test$year)/5,0)*5, by = 5),1))
Like others have stated, you may have confused the values underlying the x-axis. Playing around with abline() reveals that abline(v=2010) does not show up, but something like abline(v=50) will show up.
Here's a plot you're after, I believe (with some extra modifications):
year_vals <- as.integer(rep(1963:2014, each=10)) # pulling out of next line for easy reference
test <- data.frame(year=year_vals,response=rnorm(520))
boxplot(response~year, data=test, ylim=c(-3,3), xlab="", ylab="", range=0, xaxt="n", yaxt="n")
responselabs <- as.numeric(c(-3:3, by=1))
yearlabs <- year_vals[year_vals%%5==0] # alternate, more general definition; note that 2015 wasn't in the original 'test' data.frame #as.integer(seq(1965,2015, by=5))
axis(2, at=responselabs, tck=0.03, las=1)
# axis(1, at=1:length(yearlabs), tck=0.03)
axis(1, at=which(unique(year_vals)%in%yearlabs), labels=unique(yearlabs), tck=0.03)
Here is my first plot
par(bg="white")
image(m, main = paste("generation: ",generation), ylab="", col=heat.colors(100), xaxt="n", yaxt="n", xlab="")
It is a square, and I'd like it to be a rectangle. So I did
par(bg="white", mar=c(16,1,16,1))
image(m, main = paste("generation: ",generation), ylab="", col=heat.colors(100), xaxt="n", yaxt="n", xlab="")
But then the title (main) is really far away from the plot. So I did
par(bg="white", mar=c(16,1,16,1))
image(m, ylab="", col=heat.colors(100), xaxt="n", yaxt="n", xlab="")
legend(0.32, 3.5, paste("Generation: ", IntFormat(generation, 4)), border="white", xpd=TRUE, box.col="white", cex=1.5)
Well.. I wouldn't say it is splendid, but I was satisfied. So let's put that into a .png
png(paste0(folder.images, "pg_",IntFormat(generation,4),".png"))
par(bg="white", mar=c(16,1,16,1))
image(m, ylab="", col=heat.colors(100), xaxt="n", yaxt="n", xlab="")
legend(0.32, 3.5, paste("Generation: ", IntFormat(generation, 4)), border="white", xpd=TRUE, box.col="white", cex=1.5)
dev.off()
and here is what the .png looks like!
Is there a better solution to make a rectangle out of my square than using the parameter mar that force me to add a title with legend and to search by trial and error where the center to the picture is for the title.
Why is the .png different from what is shown in the R window?
I could achieve this:
png("test.png", res = 150, width = 8, height = 1, units = "in")
par(mar = c(1,1,1,1))
image(matrix(1:10, ncol=1), ylab="", col=heat.colors(100), xaxt="n",
yaxt="n", xlab="", main="Generation: 0001")
dev.off()
I'm trying to plot multiple line plots against a single bar plot (in this example it's grouped but doesn't have to be) but I'm running into some issues with left y-axis resizing in strange ways. It seems ok-ish when there are two lines, but then extends the axis out when there are more so the scale is wrong and doesn't line up with the bars.
I need to end up with a situation where I can customise the labels on both the left and right y-axes, hence the use of axis at the bottom of the code. In the real implementation I'll be dynamically using 'M' for million or 'K' for thousand on the left, and '%' on the right.
Any help would be very much appreciated.
x = c("a","b","c","d")
y= cbind(c(50,40,30,20), c(40,30,20,10))
y2 = c(0.80,0.65,0.75,0.50)
y3 = c(0.30,0.20,0.50,0.60)
y4 = c(0.20,0.30,0.40,0.45)
#
par(mar=c(5,8,3,5))
bp <- barplot(t(y), beside=TRUE, las=1, names.arg=x, axes=TRUE, ylim=c(0,max(y)+10), labels=c("0","10 M","20 M","30 M","40 M","50 M","60 M"))
xlim <- c(floor(min(bp)), ceiling(max(bp)))
#
par(new=T)
plot(colMeans(bp), y2, type="o", col="black", lwd=3, lty=1, xaxt="n", yaxt="n", xlab="", ylab="", xlim = xlim)
points(colMeans(bp), y2, pch=20)
par(new=T)
plot(colMeans(bp), y3, type="o", col="red", lwd=3, lty=1, xaxt="n", yaxt="n", xlab="", ylab="", xlim = xlim)
points(colMeans(bp), y3, pch=20)
par(new=T)
plot(colMeans(bp), y4, type="o", col="red", lwd=3, lty=1, xaxt="n", yaxt="n", xlab="", ylab="", xlim = xlim)
points(colMeans(bp), y4, pch=20)
axis(side=2, at=c(0,0.10,0.20,0.30,0.40,0.50,0.60), labels=c("0","10 M","20 M","30 M","40 M","50 M","60 M"), las=1, pos=0.555)
axis(side=4, pretty(c(0,max(y2))), ylim=c(0,max(y2)), col='black', ylab='', las=1 )
You can use the lines() argument for the second and third line, the everything works fine. Here is an example for the third Line:
#par(new=T)
lines(colMeans(bp), y4, type="o", col="red", lwd=3, lty=1)
points(colMeans(bp), y4, pch=20)
I need a two y-axes figure. hrbrmstr suggested to use simple plots. But when adapting the graph to my setting I observed I cannot add the ylab on the right hand side, getting a wired error:
Error in axis(4, ylim = c(0, 1), col = "black", col.axis = "black", las = 1, :
'labels' is supplied and not 'at'
Is this avoidable?
look at the code the bottom line fpr SOURCE OF ERROR
featPerf <- data.frame( expS=c("1", "2", "3", "4"),
exp1=c(1000, 0, 0, 0),
exp2=c(1000, 5000, 0, 0),
exp3=c(1000, 5000, 10000, 0),
exp4=c(1000, 5000, 10000,20000),
accuracy=c(0.4, 0.5, 0.65, 0.9) )
# make room for both axes ; adjust as necessary
par(mar=c(5, 5, 5, 7) + 0.2)
# plot the bars first with no annotations and specify limits for y
#barplot(as.matrix(featPerf[,2:5]), axes=FALSE, xlab="", ylab="", ylim=c(0, max(colSums(featPerf[2:5]))))
barplot(as.matrix(featPerf[,2:5]), axes=FALSE, xlab="", ylab="", beside=TRUE)
# make the bounding box (or not...it might not make sense for your plot)
#box()
# now make the left axis
axis(2, ylim=c(0, max(colSums(featPerf[2:5]))), col="black", las=1)
# start a new plot
par(new=TRUE)
# plot the line; adjust lwd as necessary
plot(x=1:4, y=featPerf[,6], xlab="Experiments", ylab="Abs. # of Features", axes=FALSE, type="l", ylim=c(0,1), lwd=5)
# annotate the second axis -- SOURCE OF ERROR -> VVVVVVVVVVVVVVVVVV
axis(4, ylim=c(0,1), col="black", col.axis="black", las=1, labels="Accuracy")
Like this?
par(mar=c(4,4,1,4) + 0.2)
barplot(as.matrix(featPerf[,2:5]), axes=FALSE, xlab="", ylab="", beside=TRUE)
axis(2, ylim=c(0, max(colSums(featPerf[2:5]))), col="black", las=1)
par(new=TRUE)
plot(x=1:4, y=featPerf[,6], xlab="Experiments", ylab="Abs. # of Features", axes=FALSE, type="l", ylim=c(0,1), lwd=5, col="blue")
axis(4, ylim=c(0,1), col="blue", col.axis="blue", las=1)
mtext("Accuracy",4,line=2, col="blue")
For the record, it is never a good idea to stack plots on top of each other this way (with two axes). I've made the line and the axis the same color in an attempt to draw attention to what you are doing, but this is still a very bad idea.
First of all it is not advisable to use two Y-axes in a same plot.
If you add at argument to the axis call, you get the name "Accuracy" on the right hand side of the plot.
axis(4, ylim=c(0,1), col="black", col.axis="black", las=1, labels="Accuracy",
at = .5)
I have 3 sets of data that I am trying to plot on a single plot. The first data set x values range from ~ 1 to 1700 whereas the other two data sets x values are less than 20. Therefore I want to plot them on a log axis to show variations in all the data sets. However I do not want to transform the data as I want to be able to read the values off the graph. The x axis labels I would like are 1, 10, 100 and 1000 all equally spaced. Does anyone know how to do this? I can only find examples where the data is log as well as the axis. I have attached the code I am currently using below:
Thanks in advance for any help given.
Holly
Stats_nineteen<-read.csv('C:/Users/Holly/Documents/Software Manuals/R Stuff/Stats_nineteen.csv')
attach(Stats_nineteen)
x<-Max
x1<-Min
x2<-Max
y1<-Depth
y2<-Depth
par(bg="white")
par(xlog=TRUE)
plot(x2,y1, type="n", ylim=c(555,0), log="x", axes=FALSE, ann=FALSE)
box()
axis(3, at=c(1,10,100,1000), label=c(1,10,100,1000), pos=0, cex.axis=0.6)
axis(1, at=c(1,10,100,1000), label=c(1,10,100,1000), cex.axis=0.6)
axis(2, at=c(600,550,500,450,400,350,300,250,200,150,100,50,0), label=c
(600,"",500,"",400,"",300,"",200,"",100,"",0), cex.axis=0.6)
mtext("CLAST SIZE / mm", side=3, line=1, cex=0.6, las=0, col="black")
mtext("DEPTH / m", side=2, line=2, cex=0.6, las=0, col="black")
grid(nx = NULL, ny = NULL, col = "lightgray", lty = "solid",
lwd = par("lwd"), equilogs = TRUE)
par(new=TRUE)
lines(x1,y1, col="black", lty="solid", lwd=1)
lines(x2,y2, col="black", lty="solid", lwd=1)
polygon(c(x1,rev(x2)), c(y1,rev(y2)), col="grey", border="black")
par(new=TRUE)
plot(x=Average,y=Depth, type="o",
bg="red", cex=0.5, pch=21,
col="red", lty="solid",
axes=FALSE, xlim=c(0,1670), ylim=c(555,0),
ylab = "",xlab = "")
par(new=TRUE)
plot(x=Mode,y=Depth, type="o",
bg="blue", cex=0.5, pch=21,
col="blue", lty="solid",
axes=FALSE, xlim=c(0,1670), ylim=c(555,0),
ylab = "",xlab = "")
You can do this in ggplot using scale_x_log
so something like:
myplot <- ggplot( StatsNinetee,
aes (x = myResponse,
y = myPredictor,
groups = myGroupingVariable) ) +
geom_point() +
scale_x_log()
myplot
also, avoid attach() it can give odd behavior.