Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to rasterize a single layer of a ggplot?

Tags:

r

ggplot2

Matplotlib allows to rasterize individual elements of a plot and save it as a mixed pixel/vector graphic (.pdf) (see e.g. this answer). How can the same achieved in R with ggplot2?


The following is a toy problem in which I would like to rasterize only the geom_point layer.

set.seed(1)
x <- rlnorm(10000,4)
y <- 1+rpois(length(x),lambda=x/10+1/x)
z <- sample(letters[1:2],length(x), replace=TRUE)

p <- ggplot(data.frame(x,y,z),aes(x=x,y=y)) +
  facet_wrap("z") +
  geom_point(size=0.1,alpha=0.1) +
  scale_x_log10()+scale_y_log10() +
  geom_smooth(method="gam",formula = y ~ s(x, bs = "cs"))
print(p)
ggsave("out.pdf", p)

When saved as .pdf as is, Adobe reader DC needs ~1s to render the figure. Below you can see a .png version: out.png

Of course, it is often possible to avoid the problem by not plotting raw data

like image 416
jan-glx Avatar asked Nov 10 '17 12:11

jan-glx


1 Answers

Thanks to the ggrastr package by Viktor Petukhov & Evan Biederstedt, it is now possible to rasterize individual layers. However, currently (2018-08-13), only geom_point and geom_tile are supported. and work by Teun van den Brand it is now possible to rasterize any individual ggplot layer by wrapping it in ggrastr::rasterise():

# install.packages('devtools')
# remotes::install_github('VPetukhov/ggrastr')

df %>% ggplot(aes(x=x, y=y)) +
      # this layer will be rasterized:
      ggrastr::rasterise(geom_point(size=0.1, alpha=0.1)) +
      # this one will still be "vector":
      geom_smooth()

Previously, only a few geoms were supported: To use it, you had to replace geom_point by ggrastr::geom_point_rast.

For example:

# install.packages('devtools')
# devtools::install_github('VPetukhov/ggrastr')
library(ggplot2)

set.seed(1)
x <- rlnorm(10000, 4)
y <- 1+rpois(length(x), lambda = x/10+1/x)
z <- sample(letters[1:2], length(x), replace = TRUE)

ggplot(data.frame(x, y, z), aes(x=x, y=y)) +
  facet_wrap("z") +
  ggrastr::geom_point_rast(size=0.1, alpha=0.1) +
  scale_x_log10() + scale_y_log10() +
  geom_smooth(method="gam", formula = y ~ s(x, bs = "cs"))
ggsave("out.pdf")

This yields a pdf that contains only the geom_point layer as raster and everything else as vector graphic. Overall the figure looks as the one in the question, but zooming in reveals the difference: zoom-in view of example picture Compare this to an all-raster graphic: all-raster for comparison

like image 154
jan-glx Avatar answered Sep 29 '22 13:09

jan-glx