ggrastr: Rasterize ggplot2 Layers

repository·main·Indexed 42 days ago

https://github.com/vpetukhov/ggrastr

An R package that allows users to rasterize specific layers of a ggplot2 plot. This enables the handling of large datasets, such as massive scatter plots or heatmaps, by rendering them as rasters while keeping text, axes, and labels in high-quality vector format. The primary tool is the rasterise() function, which can wrap any standard ggplot2 geom. The package also provides legacy specialized wrappers like geom_point_rast and geom_tile_rast, and a specialized geom_boxplot_jitter for jittering and rasterizing outlier points.

Tokens
5.2K
Snippets
22
Records
26
Agent score
52%

What's inside ggrastr

  1. Use `rasterise()` instead of legacy wrapper functions

    main

    ggrastr provides a modern, preferred way to rasterize specific layers in ggplot2 using the rasterise() function. This approach is superior to the legacy wrapper functions because it allows you to wrap any standard ggplot2 geom (like geom_point(), geom_tile(), or geom_beeswarm()) and control the rasterization parameters without needing a specific _rast version of that geom.

    Using rasterise() ensures that only the specified layer is rasterized, while other elements like text, axes, and labels remain in vector format, preventing the loss of quality in text elements while significantly reducing file size for plots with many points.

    ```r
    # Preferred modern approach
    gg_rasterized <- gg + rasterise(geom_point(), dpi = 300, scale = 1)
    ```埋
  2. Install ggrastr

    main

    You can install the stable version of ggrastr from CRAN or the latest development version from GitHub using devtools.

    To install the stable version:

    install.packages('ggrastr')

    To install the latest version from GitHub:

    install.packages('devtools')
    devtools::install_github('VPetukhov/ggrastr', build_vignettes = TRUE)
  3. Migrate from legacy `_rast` functions to `rasterise()`

    main

    The following table maps the legacy wrapper functions to their modern rasterise() equivalents. It is strongly encouraged to use the rasterise() pattern for all new development.

    Legacy FunctionModern Equivalent Pattern
    geom_point_rast()rasterise(geom_point(), ...)
    geom_jitter_rast()rasterise(geom_jitter(), ...)
    geom_tile_rast()rasterise(geom_tile(), ...)
    geom_beeswarm_rast()rasterise(geom_beeswarm(), ...)
    geom_quasirandom_rast()rasterise(geom_quasirandom(), ...)
    geom_violin_rast()rasterise(geom_violin(), ...)
    geom_boxplot_jitter()rasterise(geom_boxplot_jitter(), ...)
  4. Set the global default DPI with `options()`

    main

    For ggrastr versions >=0.2.2, you can set a global default resolution for all rasterized layers using R's options() function. This avoids having to specify dpi in every function call.

    # Set global DPI to 750
    options(ggrastr.default.dpi=750)
    
    # Subsequent calls will use 750 DPI
    plot + rasterise(geom_point())
    
    # Reset to default 300
    options(ggrastr.default.dpi=300)
  5. Set the default DPI globally

    main

    Instead of specifying dpi in every function call, you can set a global default for all ggrastr operations using R's options() function. This is available in ggrastr versions >=0.2.2.

    Use options(ggrastr.default.dpi = N) to set the value, where N is the desired integer resolution.

    # Set global DPI to 750
    options(ggrastr.default.dpi=750)
    
    plot <- ggplot(diamonds, aes(carat, price, colour = cut))
    new_plot = plot + rasterise(geom_point()) + theme(aspect.ratio = 1)
    print(new_plot)
    
    # Reset to default 300
    options(ggrastr.default.dpi=300)
  6. Troubleshoot R session crashes during rendering

    main

    If your R session crashes when rendering a rasterized plot, it is likely that your Cairo package was built for a different version of R.

    1. Verify Cairo version: Run the following command to check if the Built version of the Cairo package matches your current R version:
    pkgs <- as.data.frame(installed.packages(), stringsAsFactors = FALSE, row.names = FALSE)
    pkgs[pkgs$Package == 'Cairo', c("Package", "LibPath", "Version", "Built")]
    1. Test Cairo functionality: Run this command to see if Cairo causes a crash:
    Cairo::Cairo(type='raster'); dev.off()
  7. Jitter and rasterize boxplot outliers with geom_boxplot_jitter()

    main

    When dealing with a massive number of points in a boxplot, outliers can become noninformative. geom_boxplot_jitter() allows you to jitter these outliers. You can also rasterize this specific layer using the raster.dpi argument within the function.

    library(ggplot2)
    library(ggrastr)
    
    points_num <- 500000
    df <- data.frame(x=as.factor(1:points_num %% 2), y=log(abs(rcauchy(points_num))))
    gg <- ggplot(df, aes(x=x, y=y)) + scale_color_discrete(guide="none")
    
    # Jitter outliers and rasterize the layer
    gg_box_rast <- gg + geom_boxplot_jitter(
      outlier.size=0.1, 
      outlier.jitter.width=0.3, 
      outlier.alpha=0.5, 
      raster.dpi=200
    )
    print(gg_box_rast)
  8. Rasterize beeswarm and quasirandom plots

    main

    If you are using the ggbeeswarm package, you can rasterize its layers using ggrastr::rasterise(). This is the recommended way to handle beeswarm or quasirandom plots with large datasets to avoid overplotting and performance issues.

    library(ggplot2)
    library(ggrastr)
    library(ggbeeswarm)
    
    # Recommended: use rasterise() with ggbeeswarm geoms
    ggplot(mtcars) + 
      rasterise(geom_beeswarm(aes(x = factor(cyl), y=mpg)))
    
    # Alternatively, for quasirandom plots
    ggplot(mtcars) + 
      rasterise(geom_quasirandom(aes(x = factor(cyl), y=mpg)))
  9. Rasterize heatmaps with `rasterise()`

    main

    Heatmaps with large grids (e.g., 500x500) can result in very large PDF file sizes. Use rasterise() with geom_tile() to reduce the output size.

    library(ggplot2)
    library(ggrastr)
    
    coords <- expand.grid(1:500, 1:500)
    coords$Value <- 1 / apply(as.matrix(coords), 1, function(x) sum((x - c(50, 50))^2)^0.01)
    
    # Rasterized heatmap
    gg_tile_rast <- ggplot(coords) + 
      rasterise(geom_tile(aes(x=Var1, y=Var2, fill=Value)), dpi = 300, scale = 1)
    
    print(gg_tile_rast)
    library(ggplot2)
    library(ggrastr)
    coords <- expand.grid(1:500, 1:500)
    coords$Value <- 1 / apply(as.matrix(coords), 1, function(x) sum((x - c(50, 50))^2)^0.01)
    gg_tile_vec <- ggplot(coords) + geom_tile(aes(x=Var1, y=Var2, fill=Value))
    gg_tile_rast <- ggplot(coords) + rasterise(geom_tile(aes(x=Var1, y=Var2, fill=Value)), dpi = 300, scale = 1)
    print(gg_tile_rast)
  10. Rasterize heatmaps (tiles) with rasterise()

    main

    For heatmaps created with geom_tile(), use rasterise() to prevent extremely large vector files. This is particularly effective when dealing with large grids (e.g., 500x500).

    library(ggplot2)
    library(ggrastr)
    
    coords <- expand.grid(1:500, 1:500)
    coords$Value <- 1 / apply(as.matrix(coords), 1, function(x) sum((x - c(50, 50))^2)^0.01)
    
    # Rasterize the tile layer
    gg_tile_rast <- ggplot(coords) + 
      rasterise(geom_tile(aes(x=Var1, y=Var2, fill=Value)), dpi = 300, scale = 1)
    print(gg_tile_rast)
  11. Jitter and rasterize boxplots with `geom_boxplot_jitter()`

    main

    When dealing with a massive number of outliers in a boxplot, they can become noninformative and slow to render. Use geom_boxplot_jitter() to jitter the outliers and can optionally rasterize them using the raster.dpi argument.

    library(ggplot2)
    library(ggrastr)
    
    points_num <- 500000
    df <- data.frame(x=as.factor(1:points_num %% 2), y=log(abs(rcauchy(points_num))))
    
    # Jittered and rasterized boxplot
    gg_box_rast <- ggplot(df, aes(x=x, y=y)) + 
      scale_color_discrete(guide="none") + 
      geom_boxplot_jitter(outlier.size=0.1, outlier.jitter.width=0.3, outlier.alpha=0.5, raster.dpi=200)
    
    print(gg_box_rast)
    library(ggplot2)
    library(ggrastr)
    points_num <- 500000
    df <- data.frame(x=as.factor(1:points_num %% 2), y=log(abs(rcauchy(points_num))))
    gg <- ggplot(df, aes(x=x, y=y)) + scale_color_discrete(guide="none")
    gg_box_vec <- gg + geom_boxplot_jitter(outlier.size=0.1, outlier.jitter.width=0.3, outlier.alpha=0.5)
    gg_box_rast <- gg + geom_boxplot_jitter(outlier.size=0.1, outlier.jitter.width=0.3, outlier.alpha=0.5, raster.dpi=200)
    print(gg_box_rast)
  12. Rasterize scatter plots with `rasterise()`

    main

    To avoid performance issues and massive file sizes when plotting thousands of points (e.g., points_num <- 500000), use rasterise() to convert the point layer into a raster while keeping text and axes as vectors.

    library(ggplot2)
    library(ggrastr)
    
    points_num <- 10000
    df <- data.frame(x=rnorm(points_num), y=rnorm(points_num), c=as.factor(1:points_num %% 2))
    
    # Standard vector plot
    gg <- ggplot(df, aes(x=x, y=y, color=c)) + scale_color_discrete(guide="none")
    
    # Rasterized version (Preferred)
    gg_rasterized <- gg + rasterise(geom_point(), dpi = 300, scale = 1)
    print(gg_rasterized)
    library(ggplot2)
    library(ggrastr)
    points_num <- 10000
    df <- data.frame(x=rnorm(points_num), y=rnorm(points_num), c=as.factor(1:points_num %% 2))
    gg <- ggplot(df, aes(x=x, y=y, color=c)) + scale_color_discrete(guide="none")
    
    # Vector version
    gg_vec <- gg + geom_point(size=0.5)
    
    # Rasterized version using modern API
    gg_rasterized <- gg + rasterise(geom_point(), dpi = 300, scale = 1)