high-quality png without changing the multiple-plot appearance in R? - r

To produce a high-quality png file from a plot, I usually increase the value of the res = argument of the png(). But in the following case, I have a complex 7x4 plotting platform, and changing the res = changes the actual appearance of the plot (e.g., plot frames look much thicker etc.).
I am wondering how I could raise the quality of the following plot while preserving its original appearance (i.e., as shown in the graphical device)?
P.S: I'm just trying to achieve a high-quality version of what I see in my graphical device.
png("Plot.png")
par(mfcol = c(7, 4), mar = rep(.1, 4), oma = rep(7, 4))
invisible(lapply(1:28, plot, t = "n", xaxt = "n", yaxt = "n"))
dev.off()

Does this look better?
png("Plot.png", res = 600, width = 8, height = 7, units = "in")
par(mai = c(0.5,0.5,0.5,0.5))
par(mfcol = c(7, 4), mar = rep(.1, 4), oma = rep(7, 4))
invisible(lapply(1:28, function(x){
plot(rnorm(20), rnorm(20), axes = FALSE, col = sample(1:7, 1), ann = FALSE)
box()
}))
dev.off()

Depending on what you're trying to accomplish, you can also increase width and height parameters within png. As you increase res, if you increase the width and height the relative layout will stay the same, but you'll end up with more pixels so for a given physical dimension it will be higher resolution.

Related

Is it possible to change the fontsize of barplot tick mark labels with pairs_barplot in R package vcd?

With a large number of variables, the sizing of tick mark labels is too large in barplots along the diagonal of a mosaic pairs plot created with pairs_barplot() in the R vcd package. Is there any way to make them smaller? Here is a minimal working example:
library(vcd)
#> Loading required package: grid
library(vcdExtra)
#> Loading required package: gnm
pairs(table(ICU[,c(1,3:9)]),
diag_panel = pairs_barplot(
gp_vartext = gpar(fontsize = 10, fontface = 2),
gp_leveltext = gpar(fontsize = 8),
abbreviate = 1,
var_offset = 1.25))
Created on 2021-10-16 by the reprex package (v2.0.1)
Currently, you cannot set gpar() for drawing the y-axis of the bar plot explicitly. There are two general workarounds, though: (1) Not messing with the font sizes but instead plotting on a bigger device. (2) Setting an outer viewport with a different gpar(fontsize = ...) that is used as the viewports further down in the plot.
(1) Bigger device
For illustration I use a png() device here because the PNG graphic is what I embed on StackOverflow. But, of course, you could use the same trick on other devices including those that you do not create yourself but via chunk options in R/Markdown etc.
I use a device size of 13 x 13 inches (as opposed to a more common setting of 6 x 6 or 7 x 7 inches). Then I can omit all of the gpar() settings because the device is large enough to accomodate the default parameters. I still set abbreviate and var_offset, though.
png("pairs1.png", height = 13, width = 13, units = "in", res = 100)
pairs(table(ICU[, c(1, 3:9)]),
diag_panel = pairs_barplot(abbreviate = 1, var_offset = 1.25))
dev.off()
(2) Outer viewport
Alternatively, I can create a new grid page myself and push a viewport with gpar(fontsize = 7) used as the default in this viewport and its children. Then I keep your gpar() settings in pairs_barplot() and just add newpage = FALSE in the pairs() call because I want to use the page I already created.
Then all font sizes are decreased so that plotting on a 7 x 7 inches device works fine.
png("pairs2.png", height = 7, width = 7, units = "in", res = 150)
grid.newpage()
pushViewport(viewport(gp = gpar(fontsize = 7)))
pairs(table(ICU[, c(1, 3:9)]),
diag_panel = pairs_barplot(
gp_vartext = gpar(fontsize = 10, fontface = 2),
gp_leveltext = gpar(fontsize = 8),
abbreviate = 1, var_offset = 1.25),
newpage = FALSE)
dev.off()

Plotting 3 columns of rasters and saving into pdf with base R

Sorry this example is not entirely reproducible (I do not provide exact input data), but hopefully the example will be clear.
In short, I would like to save three maps in a wide pdf format, so All three maps can be shown with a desired extent + there is an overarching title above (but I don't want it to take up half of the page).
I am really struggling with setting it up properly:
pdf("plots1.pdf",width = 30/2.54,height = 20/2.54)
par(mfrow = c(2,3))
layout(matrix(c(1,1,1,2,3,4), 2, 3, byrow = TRUE))
plot.new()
text(0.5,0.5,"Africa, Params_1",cex=2,font=2)
# plot.new()
# plot.new()
plot(r2_list[[1]], xlim = Region[[g]][1:2], ylim = Region[[g]][3:4],
breaks=cuts, col = plasma(21), main = variable[1],legend=FALSE)
plot(wrld_simpl,add=TRUE)
plot(r2_list[[2]], xlim = Region[[g]][1:2], ylim = Region[[g]][3:4],
breaks=cuts, col = plasma(21), main = variable[2],legend=FALSE)
lines(wrld_simpl)
plot(r2_list[[3]], xlim = Region[[g]][1:2], ylim = Region[[g]][3:4],
breaks=cuts, col = plasma(21), main = variable[3])
lines(wrld_simpl)
dev.off()
I would also like to try to print 6 plots, again - with overarching titles but I fail miserably.
Help will be much appreciated.
Add heights= to your layout call.
layout(matrix(c(1,1,1, 2,3,4), byrow=TRUE, nr=2), heights = c(1, 8))
opar <- par(mar=c(0,0,0,0))
plot.new()
text(0.5,0.5,"Africa, Params_1",cex=2,font=2)
par(opar)
plot(1:20)
plot(3:99)
plot(1:2)
(Blue boundaries below added externally, for reference only.)
Without heights
If I remove the heights= from the code above, I see this:
With heights
(You will want to play with the actual values based on your canvas size, etc.)

Enlarge single symbol (/) in R expression

I have the following code:
plot(x = 1, y = 1, xlim = c(1,2), ylim = c(1,2),
ylab = expression(bgroup("(",A[B]^{C},")")[~D[2]] / bgroup("(",E[F]^{G},")")[~H]))
Which leads to this plot:
Is it possible to make the division symbol ("/") taller so it properly divides two expression and doesn't look like it's shooting out of D2?
My attempt at manually drawing it with cex>1 lead to an ugly and fat division symbol. I don't want it fatter, just taller.
I am looking for solutions that use base plot methods.
If you don't mind using latex, you can export the plot using tickz. That will unleash the full power of latex formatting. E.g. with a standard sized division sign it looks like this:
library(devtools)
install_github('daqana/tikzDevice')
library(tikzDevice)
tikz('test.tex', width = 4, height = 3)
par(mar=c(3,6,3,3))
plot(x = 1, y = 1,
xlim = c(1,2), ylim = c(1,2),
ylab = '$(A_B^C)_{D_2} / (E_F^G)_{H}$')
dev.off()
or if you want an even bigger division sign, you can use one of the latex codes (in ascending order of size) \big/, \Big/, \bigg/, or \Bigg/:
tikz('test.tex', width = 4, height = 3)
par(mar=c(3,6,3,3))
plot(x = 1, y = 1,
xlim = c(1,2), ylim = c(1,2),
ylab = '$\\left(A_B^C\\right)_{D_2} \\bigg/ \\left(E_F^G\\right)_{H}$')
dev.off()

Showing axes in bitmap plot in R and scaling bitmap plot

I am trying add axes to the bitmap plot in R. But its not showing those axes. I am using OS X 10.10 with R v3.3.0
set.seed(0)
#Sample matrix
bitmap<-matrix(rnorm(150000,mean=1:500),nrow = 300, ncol = 500)
image(bitmap,col = RColorBrewer::brewer.pal(9,"Greys"), axes=FALSE,
useRaster = TRUE)
axis(1,at = seq(from=1000,to = 10000,length.out = 19),
labels = seq(from=1000,to = 10000,length.out = 19))
axis(2,at = seq(from=0,to = 100,length.out = 11),
labels = seq(from=0,to = 100,length.out = 11))
How to show these required axes with required ranges in R ?
How to specify the size of the plotted bitmap in R, either in terms of pixels or in some length unit ?
How can I scale bitmap's width and height independently ?
Is there any other R package which will allow me addressing these parameters in a better way ?
image() scales both axes to 1. You just need to adjust your at= values
axis(1,at = seq(from=1000,to = 10000,length.out = 19)/10000,
labels = seq(from=1000,to = 10000,length.out = 19))
axis(2,at = seq(from=0,to = 100,length.out = 11)/100,
labels = seq(from=0,to = 100,length.out = 11))
The size of the rendered image is based on your current graphics device. You cannot explicitly control the size of the drawing area in pixels, just the overall plot size (with axes and everything). Graphics in R tend to grow and shrink depending on window size. You can fix the aspect ratio if you like with asp=1 in the plot() call.
If you need pixel-level control, you might want to use some other program for plotting.

Set plot margin of png plot device using par

I've created a choropleth of Brazil. When saving the plot in .png, the upper and the lower part of the plot are lost (covered). Here are the lines to save the plot.
plot.new()
par(omi=c(0,0,0,0), mgp=c(0,0,0),mar=c(0,0,0,0) , family = "D")
par(mfrow=c(1,1),cex=1,cex.lab = 0.75,cex.main=0.2,cex.axis=0.2)
png(filename = "map_cons_g.png", width = 6,height = 6, units = "in", res = 600)
plot(c(-75,-35),c(0,-30),type="n",axes=FALSE,xlab="",ylab="",asp=1.2)
plot(Brazil,col=cols[Brazil$Cons.g_ri],add=TRUE,border="black",lwd=0.5)
dev.off()
For saving the plot without losing the upper and the lower part of the map, I must change the coordinates to add white space at the bottom and at the top (i.e. replace c(0,-30) by c(5,-33)):
plot.new()
par(omi=c(0,0,0,0), mgp=c(0,0,0),mar=c(0,0,0,0) , family = "D")
par(mfrow=c(1,1),cex=1,cex.lab = 0.75,cex.main=0.2,cex.axis=0.2)
png(filename = "map_cons_g.png", width = 6,height = 6, units = "in", res = 600)
plot(c(-75,-35),c(5,-33),type="n",axes=FALSE,xlab="",ylab="",asp=1.2)
plot(Brazil,col=cols[Brazil$Cons.g_ri],add=TRUE,border="black",lwd=0.5)
dev.off()
This works in the sense that I can see the full map but the map then does not use all the available area in the figure. It seems that there are some margin in the upper and the lower part of the figure when saving the plot. I've never had that problem with other types of plot.
Sorry, I don't have enough "reputation" to post images to show you how the maps look like.
Any idea of how to fix this?
Edit:
The comments below got me searching more into the problem and I finally found a fix. I apologize as I now realized that I did not understand the source of the problem and thus did not explain as best as I could have,
It seems that png resets the outer margin of the plot. Thus, even though I had set omi=c(0,0,0,0), those were not the value used by the png command in saving the plot. The solution was to set the plot parameters after calling png so save the figure.
plot.new()
png(filename = "map_cons_g.png", width = 6,height = 6, units = "in", res = 600)
par(omi=c(0,0,0,0), mgp=c(0,0,0),mar=c(0,0,0,0) , family = "D")
par(mfrow=c(1,1),cex=1,cex.lab = 0.75,cex.main=0.2,cex.axis=0.2)
plot(c(-75,-35),c(5,-33),type="n",axes=FALSE,xlab="",ylab="",asp=1.2)
plot(Brazil,col=cols[Brazil$Cons.g_ri],add=TRUE,border="black",lwd=0.5)
dev.off()
From Details in ?par:
Each device has its own set of graphical parameters.
Thus, even though I had set the outer margin of the plot in par (omi = c(0,0,0,0)), those value were overwritten by the parameters in png when saving the plot.
The solution was to set the margin parameters in par after calling png
plot.new()
# first open png device...
png(filename = "map_cons_g.png", width = 6,height = 6, units = "in", res = 600)
# ...then set par
par(omi = c(0,0,0,0), mgp = c(0,0,0), mar = c(0,0,0,0), family = "D")
par(mfrow = c(1, 1), cex = 1, cex.lab = 0.75, cex.main = 0.2, cex.axis = 0.2)
plot(c(-75, -35), c(5, -33), type = "n", axes = FALSE, xlab = "", ylab = "", asp = 1.2)
plot(Brazil, col = cols[Brazil$Cons.g_ri], add = TRUE, border = "black", lwd = 0.5)
dev.off()

Resources