I want to produce two figures using base R, both showing barplots. The first figure should contain two bar plots and the second figure should contain four bar plots.
I used par(mfrow = c(...)) to arrange multiple bar plots in one figure. I don't have trouble to produce the figures themselves, but when I save the figures bar widths and tick labels are different in size.
To my understanding, when I produce the second figure with four bar plots and chose double the width of the first figure when exporting, bars and labels should be displayed with the same size in the file. However, the labels are much smaller and the bars have a different width in the second figure. Can anyone tell me why?
Here a simple example:
png(filename="plot1.png", width=200, height=300, bg="white")
par(mfrow = c(1, 2), mar = c(1, 2, 1, 1), oma = c(0, 0, 0, 0))
barplot(height = c(2,3), width = 1, xlim = c(0,2))
barplot(height = c(2,3), width = 1, xlim = c(0,2))
dev.off()
png(filename="plot2.png", width=400, height=300, bg="white")
par(mfrow = c(1, 4), mar = c(1, 2, 1, 1), oma = c(0, 0, 0, 0))
barplot(height = c(2,3), width = 1, xlim = c(0,2))
barplot(height = c(2,3), width = 1, xlim = c(0,2))
barplot(height = c(2,3), width = 1, xlim = c(0,2))
barplot(height = c(2,3), width = 1, xlim = c(0,2))
dev.off()
Plot 1:
Plot 2:
Probably par
and pdf(width, height)
should be equal.
png(filename="plot1.png", width=400, height=300, bg="white")
par(mfrow=c(1, 4), mar=c(1, 2, 1, 1), oma=c(0, 0, 0, 0))
replicate(2, barplot(height=c(2,3), width=1, xlim=c(0,2)))
dev.off()
png(filename="plot2.png", width=400, height=300, bg="white")
par(mfrow=c(1, 4), mar=c(1, 2, 1, 1), oma=c(0, 0, 0, 0))
replicate(4, barplot(height=c(2,3), width=1, xlim=c(0,2)))
dev.off()
Another solution is to use layout
.
def.par <- par(no.readonly=TRUE) # save par default, for resetting...
# 1 x 2 plot
layout(matrix(c(1:2, 0, 0), nrow=1, ncol=4, byrow=TRUE))
layout.show(n=2) # to inspect layout # MARK
replicate(2, barplot(height=c(2,3), width=1, xlim=c(0,2)))
# 1 x 4 plot
layout(matrix(c(1:4), nrow=1, ncol=4, byrow=TRUE))
layout.show(n=4) # to inspect layout
replicate(4, barplot(height=c(2,3), width=1, xlim=c(0,2)))
# 2 x 4 plot
layout(matrix(c(1:2, 0, 0, 3:6), nrow=2, ncol=4, byrow=TRUE))
layout.show(n=6) # to inspect layout
replicate(2, barplot(height=c(2,3), width=1, xlim=c(0,2)))
replicate(4, barplot(height=c(2,3), width=1, xlim=c(0,2)))
par(def.par) # reset to default
However, both solutions bring a half empty plot 1, the reason can be seen in code above at # MARK
.
We could use the magick
package to "chop" the first plot to the desired content. First we create the *.png
s with the second method.
clr <- "#ED7C22" # color
png(filename="plot1.png", width=400, height=300, bg="white")
layout(matrix(c(1:2, 0, 0), nrow=1, ncol=4, byrow=TRUE))
replicate(2, barplot(height=c(2,3), width=1, xlim=c(0,2), col=clr, border=0))
dev.off()
png(filename="plot2.png", width=400, height=300, bg="white")
layout(matrix(c(1:4), nrow=1, ncol=4, byrow=TRUE))
replicate(4, barplot(height=c(2,3), width=1, xlim=c(0,2), col=clr, border=0))
dev.off()
Now, using image_chop
we trim plot1.png
to it's left half.
library(magick)
(i <- image_read("plot1.png"))
i.chopped <- image_chop(i, "200x+200") # says: trim by 200px at pos. 200
Finally, we export the chopped image.
image_write(i.chopped, path="plot1.ch.png", format="png")