Can't increase title and x/y label size in a ggplot2 plot saved as a PNG file, but it works fine on screen - r

I am hitting a small, but not insignificant brick wall with this oft asked and answered question.
I am using Rstudio 0.97.336 and R 3.0.0 on Linux. I am making a (much more complex) graph to put in a paper. The default size of the title and x/y labels are too small to be easily read. However the obvious method for fixing this using the theme function on element_text
theme(axis.title.y = element_text(size = rel(1.8))
does not work, if I save the image as a PNG file. It does however work, exactly as expected, when I'm looking at the images in RStudio. The code below reproduces my problem exactly.
##Libraries
library(ggplot2)
set.seed(15612)
##Generate data
Year <- seq(2000,2010)
data <- -2*(Year - 2005) + 10 + runif(11,min=-3,max=3)
Title <- "Title for our graph"
xlab <- "X label"
ylab <- "Y label"
df <- data.frame(Year,data)
##Plot
##First image with small title, xlab, ylab
image1 <- ggplot(df) +
geom_line(aes(x=Year,y=data)) +
theme_bw() +
labs(title=Title,xlab=xlab,ylab=ylab)+
theme(panel.border = element_rect(fill = NA, colour="grey70"))
image1
ggsave("Image1.png",image1, width=15,height=10,units='cm')
##Second image with larger title, xlab, ylab
image2 <- image1 +
theme(axis.title.y = element_text(size = rel(1.8), angle = 90)) +
theme(axis.title.x = element_text(size = rel(1.8), angle = 00)) +
theme(plot.title = element_text(size = rel(2.0), angle = 00))
image2
ggsave("Image2.png",image2, width=15,height=10,units='cm')
dev.off()
image1
image2
These images look exactly as expected on the screen in Rstudio. Image 1 has small font sizes for the title, etc. and image 2 has larger more legible font sizes. Unfortunately, when saved as png files, they are identical, and both have small fonts for the title, x and y labels.
I can't (yet) post images, so if you look at these two urls, you will see the problem.
Image 1 - small title font
Image 2 - still a small title font, but ought to be bigger
I cannot see where I am going astray. I know there are issues (or features!) with lazy evaluation in ggplot2, but I don't see where this is biting me. I would be very grateful for any help with this,
Regards,
Anthony Staines

Using RStudio, I am also seeing some strange behaviour (but I need to look into the docs a bit more to decide if it is not as we should expect), however, I think you can get the output you expect by calling ggsave, letting it use it's default plot = last.plot(), then running the plot then calling dev.off() between the plots. i.e.
The workaround
ggsave("~/Image1.png", width=15,height=10,units='cm')
image1
dev.off()
ggsave("~/Image2.png", width=15,height=10,units='cm')
image2
dev.off()
A reproducible example of this behaviour
If we try the following example in RStudio I can get the same behaviour as the OP. Running the first code block below in RGui 3.0.0 gives us what we expect, i.e. the 3rd picture. However this is what happens in RStudio:
## Make plot and save
qp <- qplot(1:5, rnorm(5), size = I(2) )
qp
ggsave("~/Image1.png", width=15,height=10,units='cm')
## Make new plot
qp <- qplot(1:10, rnorm(10), size = I(5) )
qp
ggsave("~/Image2.png", width=15,height=10,units='cm')
At this point if we try to open the files that are saved we get:
Then we just run dev.off()
## Without calling dev.off() plot 1 is still open and displays nothing
## Plot two is accessible from the filesystem
## Calling dev.off() we then get both plots, but BOTH plots
## use settings from plot 2
dev.off()
And we get:
Now if we try and save the plots by calling ggsave then printing the plots to screen and then calling dev.off() it works as expected:
## Now we try calling dev.off() between plots:
qp <- qplot(1:5, rnorm(5), size = I(2) )
ggsave("~/Image1.png", width=15,height=10,units='cm')
qp
dev.off()
## Make new plot
qp <- qplot(1:10, rnorm(10), size = I(5))
ggsave("~/Image2.png", width=15,height=10,units='cm')
qp
dev.off()
We then get:

Related

ggplot2: CairoSVG changes point size

I build scatterplots using ggplot2 in R. I then want to save them as svg files with Cairo::CairoSVG. It seems to work fine except for the point size, which is enlarged in the resulting .svg file.
Here comes some example code:
library (ggplot2)
my_plot <- ggplot(mpg, aes(cty, hwy)) +
geom_point(size = 0.5)
x11 (width = 6, height = 6)
my_plot
Cairo::CairoSVG (file = "my_path",
width = 6, height = 6)
print (my_plot)
dev.off()
And this is what I get: on the right hand, the plot printed in R and on the left side the saved .svg-file opened in Inkscape. It looks fine except for the point size, which is a pity. Are there any ideas on how to get the right point-size? I tried different point sizes and also shapes, with similarly unmatched results.
Note that I seek to stick with Cairo::CairoSVG, beacuse in the final plots I wish to use custom fonts which are printed nicely with Cairo::CairoSVG. Any help is appreciated.
EDIT: I am working on a Windows machine.
Preliminary remark: when you pass width = 6, height = 6 in the Cairo::CairoSVG() parameters, you provide potentially different parameters (resolution and display) from the ones used in the RStudio plot panel.
To get the exact same image than the one rendered in the panel as well as using Cairo, you can use this alternative (dev.size('px') returns the dimensions of the current plot panel):
library (ggplot2)
my_plot <- ggplot(mpg, aes(cty, hwy)) +
geom_point(size = 0.5)
my_plot
mirror <- recordPlot()
png(filename = "mypath",
width = dev.size('px')[1]/96,
height = dev.size('px')[2]/96,
res = 96, # base RStudio resolution
units = "in",
type = "cairo") # calls CairoSVG
replayPlot(mirror)
dev.off()
(Note : I prefer the use of png() rather than ggsave() because it will save the entire last plot. I have observed that ggsave() would save only the last facet of a grid, for example)

Automatically adjust plot title width using ggplot

I am fairly new to R/ggplot2 and still learning on the go. Hopefully I am not missing something obvious!
I am trying to create several different plots using ggplot2 that I am layouting using the function plot_grid from the cowplot package to make the plots visible side by side and add plot numeration and captions. The problem is that if the generated plots are displayed in a small window or I have many plots beside one another then the titles of the two plots sometimes overlap. To solve this problem I tried to automatically insert line breaks in my too long titles using code I found in another thread since I wanted the text size of the titles to stay constant.
Using the following code I can easily automatically insert the necessary line breaks to make my title a specific width, but the problem is that I always need to enter a numeric value for the width. Depending on the number of plots I am inserting this value would of course change. I could of course go through my code and manually set the width for each set of plots until it is the correct value, but I was hoping to automate this process so that the title width is adjusted automatically to match the width of the x-axis. Is there anyway to implement this in R?
#automatically line break and add titles
myplot_theme1 = function (plot, x.title = NULL, y.title = NULL, plot.title = NULL) {
plot +
labs(title = paste(strwrap(plot.title, width = 50), collapse = "\n"),
x = x.title,
y = y.title)
}
# generate an example plot
data_plot <- data.frame(x = rnorm(1000), y = rnorm (1000))
plot1 <- ggplot(data_plot, aes(x = x, y = y)) + geom_point()
title <- "This is a title that is very long and does not display nicely"
myplot_theme1(plot1, plot.title = title)
My test plot
I have tried searching but I haven't found any solutions that seem to address what I am looking for. The only solution I did find that looked promising was based on the package gridDebug. This packages doesn't seem to be supported by my operating system anymore though (macOS Sierra Version 10.12.6) since when I try to install it I get the following error message:
Warning in install.packages: dependencies ‘graph’, ‘Rgraphviz’ are not available
And on the CRAN package documentation it states that the package is not even available for macOS El Capitan which was my previous operating system. If someone knows what is causing this issue so that I could try the solution from the above thread that would of course be great as well.
One idea (but perhaps not an ideal solution) is to adjust the size of text based on the number of characters in the title. You can adjust ggplot properties using theme and in this case you want to adjust plot.title (the theme property, not your variable). plot.title has elements size and horizontal justification hjust, the latter is in range [0,1].
# generate an example plot
data_plot <- data.frame(x = rnorm(1000), y = rnorm (1000))
plot1 <- ggplot(data_plot, aes(x = x, y = y)) + geom_point()
title1 <- "This is a title that is very long and does not display nicely"
title2 <- "I'm an even longer sentence just test me out and see if I display the way you want or you'll be sorry"
myplot_theme1 = function (plot, x.title = NULL, y.title = NULL, plot.title = NULL) {
plot +
labs(title = plot.title,
x = x.title,
y = y.title) +
theme(plot.title = element_text(size=800/nchar(plot.title), hjust=0.5)) # 800 is arbitrarily chosen
}
myplot_theme1(plot1, plot.title = title1)
myplot_theme1(plot1, plot.title = title2)

Output Stem and Leaf Plot to Image

I'm trying to output a Stem and Leaf plot in R as an image. I'm not sure if there's a nice library which can accomplish this but below is some of the code I've tried.
jpeg(filename="stem.jpeg",width=480,height=480, units="px",pointsize=12)
plot.new()
tmp <- capture.output(stem(men, scale = 1, width = 40))
text( 0,1, paste(tmp, collapse='\n'), adj=c(0,1), family='mono' )
dev.off()
This above code resulted in the data being saved, but it looks very blurry and the plot gets cut off pretty badly. When adding a histogram to an image, R seems to do a good job to scale everything to fit in the size of the image.
jpeg(filename="stem.jpeg",width=480,height=480,
units="px",pointsize=12)
stem(men, scale = 1, width = 40)
dev.off()
This created the image but had no content within it.
Any ideas? Thanks!
That's because stem and leaf plots produce text not images. You can save the text as follows using the sink command: http://stat.ethz.ch/R-manual/R-devel/library/base/html/sink.html
sink(file=“Stem.txt”)
stem(men, scale = 1, width = 40)
sink(file=NULL)
unlink("stem.txt")
To export a stemplot as graphics, you can use a vector graphics format, such
as .eps, .pdf, or .emf. For example, a windows metafile:
win.metafile("stem.wmf", pointsize = 10)
plot.new()
tmp <- capture.output(stem(mtcars$mpg))
text(0,1,paste(tmp,collapse='\n'),family='mono',adj=c(0,1))
dev.off()

High resolution autoplot function in R studio

I get one good plot with autoplot function in R studio. If I click in zoom a get a expected picture of my plot. However i would like to export in high resolution. This was my last command.
autoplot(bed, layout = "karyogram", aes(color = score, fill = score), res = 1200)
Put tiff("figurename.tif", units="in", width=11, height=8.5, res=300) before start the comands. After, put dev.off() to write a plot as tiff format in your disk.

R ggplot: geom_tile lines in pdf output

I'm constructing a plot that uses geom_tile and then outputting it to .pdf (using pdf("filename",...)). However, when I do, the .pdf result has tiny lines (striations, as one person put it) running through it. I've attached an image showing the problem.
Googling let to this thread, but the only real advice in there was to try passing size=0 to geom_tile, which I did with no effect. Any suggestions on how I can fix these? I'd like to use this as a figure in a paper, but it's not going to work like this.
Minimal code:
require(ggplot2)
require(scales)
require(reshape)
volcano3d <- melt(volcano)
names(volcano3d) <- c("x", "y", "z")
v <- ggplot(volcano3d, aes(x, y, z = z))
pdf("mew.pdf")
print(v + geom_tile(aes(fill=z)) + stat_contour(size=2) + scale_fill_gradient("z"))
This happens because the default colour of the tiles in geom_tile seems to be white.
To fix this, you need to map the colour to z in the same way as fill.
print(v +
geom_tile(aes(fill=z, colour=z), size=1) +
stat_contour(size=2) +
scale_fill_gradient("z")
)
Try to use geom_raster:
pdf("mew.pdf")
print(v + geom_raster(aes(fill=z)) + stat_contour(size=2) + scale_fill_gradient("z"))
dev.off()
good quality in my environment.
I cannot reproduce the problem on my computer (Windows 7), but I remember it was a problem discussed on the list for certain configurations. Brian Ripley (if I remember) recommended
CairoPDF("mew.pdf") # Package Cairo
to get around this
In the interests of skinning this cat, and going into waaay too much detail, this code decomposes the R image into a mesh of quads (as used by rgl), and then shows the difference between a raster plot and a "tile" or "rect" plot.
library(raster)
im <- raster::raster(volcano)
## this is the image in rgl corner-vertex form
msh <- quadmesh::quadmesh(im)
## manual labour for colour scaling
dif <- diff(range(values(im)))
mn <- min(values(im))
scl <- function(x) (x - mn)/dif
This the the traditional R 'image', which draws a little tile or 'rect()' for every pixel.
list_image <- list(x = xFromCol(im), y = rev(yFromRow(im)), z = t(as.matrix(im)[nrow(im):1, ]))
image(list_image)
It's slow, and though it calls the source of 'rect()' under the hood, we can't also set the border colour. Use 'useRaster = TRUE' to use 'rasterImage' for more efficient drawing time, control over interpolation, and ultimately - file size.
Now let's plot the image again, but by explicitly calling rect for every pixel. ('quadmesh' probably not the easiest way to demonstrate, it's just fresh in my mind).
## worker function to plot rect from vertex index
rectfun <- function(x, vb, ...) rect(vb[1, x[1]], vb[2,x[1]], vb[1,x[3]], vb[2,x[3]], ...)
## draw just the borders on the original, traditional image
apply(msh$ib, 2, rectfun, msh$vb, border = "white")
Now try again with 'rect'.
## redraw the entire image, with rect calls
##(not efficient, but essentially the same as what image does with useRaster = FALSE)
cols <- heat.colors(12)
## just to clear the plot, and maintain the plot space
image(im, col = "black")
for (i in seq(ncol(msh$ib))) {
rectfun(msh$ib[,i], msh$vb, col = cols[scl(im[i]) * (length(cols)-1) + 1], border = "dodgerblue")
}

Resources