R: function to scale ggplot2, lattice or base R gr

2019-03-18 21:50发布

问题:

In R I always find it annoying that base R, lattice and ggplot2 plots all work with absolute point sizes for the size of text and plot symbols.

This means that if you increase say the size of your plot window to get a page-filling graph from

windows(width=5,height=5);qplot(Sepal.Length, Petal.Length, data = iris, color = Species, size = Petal.Width, alpha = I(0.7))

to

windows(width=10,height=10);qplot(Sepal.Length, Petal.Length, data = iris, color = Species, size = Petal.Width, alpha = I(0.7))

that the relative scaling of the text and plot symbols change relative the rest. The same applies to base R and lattice plots.

In the context of some graph export functions I am writing I was wondering if it would be possible to write a function that would take the output of the current graphics device (which can be accessed using recordPlot()), and scale all plot symbols and text as well as line widths by an arbitrary %, thereby allowing the graph to be exported at any size, whilst still maintaining the same look? I.e. a function to proportionally scale the whole graph to a larger or smaller size while keeping the look the same?

PS the same would be required to be able to scale the RStudio plot window on high DPI 4K screens and still make it legible (right now RStudio uses pixel doubling but this makes the plot window look really fuzzy, and also causes problems in combination with Cleartype on Windows, causing colour fringing).

回答1:

for some reason the point size is encoded as fontsize, so it doesn't seem easy to convert it to units that would scale automatically. If you know what scaling you'd want to apply, then the following might help

library(ggplot2)
p <- qplot(Sepal.Length, Petal.Length, data = iris, 
           geom=c("point","line"),
           color = Species, size = Petal.Width, alpha = I(0.7))

library(gtable)
library(grid)

g <- ggplotGrob(p)
pts <- g$grobs[[4]][["children"]][[2]] # geom_point layer
lns <- g$grobs[[4]][["children"]][[3]] # geom_line layer
g$grobs[[4]][["children"]][[2]] <- editGrob(pts, size=1.2*pts$size)
gp <- modifyList(lns$gp, list(lwd=1.2*lns$gp$lwd))
g$grobs[[4]][["children"]][[3]] <- editGrob(lns, gp=gp)

grid.newpage()
grid.draw(g)



回答2:

This seems to be closer to your end goal

library(ggplot2)
p <- qplot(Sepal.Length, Petal.Length, data = iris, 
           geom=c("point","line"),
           color = Species, size = Petal.Width, alpha = I(0.7))
library(grid)
print(p, vp=viewport(gp=gpar(cex=2, lex=2)))