--- title: "ggfun: Utilities and Extensions for ggplot2" author: "Guangchuang Yu" date: "`r Sys.Date()`" vignette: > %\VignetteIndexEntry{ggfun: Utilities and Extensions for ggplot2} %\VignetteEngine{quarto::html} %\VignetteEncoding{UTF-8} --- ```{r} #| label: setup #| include: false knitr::opts_chunk$set( collapse = TRUE, comment = "#>", fig.width = 6, fig.height = 4, message = FALSE, warning = FALSE ) library(grid) library(ggplot2) library(ggfun) source_root <- normalizePath(file.path(".."), winslash = "/", mustWork = FALSE) if (file.exists(file.path(source_root, "DESCRIPTION")) && requireNamespace("pkgload", quietly = TRUE)) { pkgload::load_all(source_root, quiet = TRUE) } theme_set(theme_bw()) ``` `ggfun` collects small but useful extensions for `ggplot2`. The package focuses on tools that make it easier to style plots, add custom geometric layers, work with legends, and inspect or modify existing plot objects. This vignette groups the functions by the type of task they solve. ## Theme Elements ### Rounded rectangles `element_roundrect()` works like `element_rect()`, but draws rounded rectangle backgrounds. It can be used in theme elements such as facet strips, legends, panel backgrounds, and plot backgrounds. ```{r} #| label: rounded-strip p <- ggplot(mpg, aes(displ, cty)) + geom_point(alpha = 0.7) + facet_grid(cols = vars(cyl)) p + theme( strip.background = element_roundrect( fill = "grey35", color = NA, r = 0.15 ), strip.text = element_text(color = "white") ) ``` ```{r} #| label: rounded-legend ggplot(mtcars, aes(mpg, disp, color = factor(cyl), size = wt)) + geom_point(alpha = 0.8) + theme( legend.background = element_roundrect( fill = "grey97", color = "grey55", linetype = 2, r = 0.08 ) ) ``` ### Alternating grid bands `element_blinds()` and `theme_blinds()` draw alternating bands on major grid lines. This is useful when categorical axes need more visual separation. ```{r} #| label: theme-blinds df_blinds <- data.frame( group = rep(LETTERS[1:6], each = 3), sample = rep(c("A", "B", "C"), 6), value = c(2, 4, 3, 5, 3, 4, 4, 6, 5, 6, 5, 7, 3, 4, 6, 5, 7, 6) ) ggplot(df_blinds, aes(sample, group)) + geom_point(aes(size = value, color = value)) + scale_color_viridis_c() + theme_blinds(axis = "y", colour = c("grey95", "white")) + theme(panel.grid.major.x = element_blank()) ``` ### Minimal plot backgrounds Several small theme helpers remove common plot decorations. ```{r} #| label: theme-helpers ggplot(mtcars, aes(mpg, disp)) + geom_point(aes(color = factor(cyl)), size = 2) + theme_noxaxis() ``` ```{r} #| label: theme-transparent ggplot(mtcars, aes(mpg, disp)) + geom_point(aes(color = factor(cyl)), size = 2) + theme_transparent() ``` ## Geometric Layers ### Histograms based on `hist()` `geom_hist()` uses `hist()` to compute break midpoints and counts. This makes it useful when the goal is to reproduce base R histogram calculations inside a `ggplot2` layer. ```{r} #| label: geom-hist set.seed(42) df_hist <- data.frame( value = c(rnorm(120), rnorm(120, mean = 2)), group = rep(c("A", "B"), each = 120) ) ggplot(df_hist, aes(value, fill = group)) + geom_hist(breaks = 16, position = "identity", alpha = 0.55, color = "white") ``` ### X-splines `geom_xspline()` draws an X-spline through control points. Positive `shape` values produce smoother curves, while negative values pull the curve toward the control points. ```{r} #| label: geom-xspline set.seed(123) df_line <- data.frame( x = rep(1:10, 2), y = c(cumsum(rnorm(10)), cumsum(rnorm(10, sd = 0.7)) + 2), series = rep(c("A", "B"), each = 10) ) ggplot(df_line, aes(x, y, color = series, group = series)) + geom_point(size = 2) + geom_xspline(linewidth = 1, shape = 1) ``` ### Continuous-color segments `geom_segment_c()` draws line segments whose colors transition from `col0` to `col1`. ```{r} #| label: geom-segment-c df_segments <- data.frame( x = c(0, 1, 2, 3), xend = c(1, 2, 3, 3), y = c(0, 1, 0.5, 0), yend = c(1, 0.5, 1.5, 1.5), start = c(0.1, 0.3, 0.5, 0.7), end = c(0.4, 0.6, 0.9, 1.0) ) ggplot(df_segments) + geom_segment_c( aes(x = x, y = y, xend = xend, yend = yend, col0 = start, col1 = end), linewidth = 2, lineend = "round" ) + scale_color_viridis_c(name = "value") + coord_equal() ``` ### Shape-like point layers `geom_scatter_rect()`, `geom_triangle()`, and `geom_cake()` are convenient when a plot needs custom glyph-like markers. ```{r} #| label: geom-scatter-rect df_rect <- data.frame( x = rep(1:5, 2), y = rep(1:2, each = 5), value = c(1, 3, 2, 4, 5, 2, 4, 3, 5, 6) ) ggplot(df_rect, aes(x, y)) + geom_scatter_rect(aes(fill = value), width = 0.85, height = 0.5, color = "white") + scale_y_continuous(breaks = 1:2, labels = c("control", "treated")) + scale_fill_viridis_c() ``` ```{r} #| label: geom-custom-glyphs df_glyph <- data.frame( x = 1:4, y = c(1, 2, 1.4, 2.4), angle = c(0, 45, 90, 135), cake_size = c(0.18, 0.2, 0.16, 0.22) ) ggplot(df_glyph, aes(x, y)) + geom_triangle(aes(angle = angle), fill = "tomato", size = 16, alpha = 0.8) + geom_cake(aes(y = y + 0.45, size = cake_size), colour.cake = "pink") + coord_equal(xlim = c(0.5, 4.5), ylim = c(0.5, 3.2)) + theme_noaxis() ``` ## Facets and Plot Data ### Updating facet labels `facet_set()` can relabel existing facets or add a simple facet strip to a plot. ```{r} #| label: facet-set-labels p_facet <- ggplot(mtcars, aes(disp, drat)) + geom_point() + facet_grid(cols = vars(am), rows = vars(cyl)) p_facet + facet_set(label = c(`0` = "Automatic", `1` = "Manual", `6` = "Six cylinders")) ``` ```{r} #| label: facet-set-single ggplot(mtcars, aes(mpg, disp)) + geom_point() + facet_set("Motor Trend cars") ``` ### Extracting mapped data `get_aes_var()` returns the variable used by a mapping, and `get_plot_data()` extracts variables from the data associated with a plot or layer. ```{r} #| label: plot-data p_data <- ggplot(mtcars, aes(mpg, disp, color = factor(cyl))) + geom_point() get_aes_var(p_data$mapping, "x") head(get_plot_data(p_data, var = c("x", "y"))) ``` `xrange()`, `yrange()`, and `ggrange()` summarize the visible data range of a plot. ```{r} #| label: plot-range xrange(p_data) yrange(p_data) ggrange(p_data, var = "x", region = "plot", type = "range") ``` ## Legends and Fonts `get_legend()` extracts the legend grob from a plot. ```{r} #| label: get-legend p_legend <- ggplot(mtcars, aes(mpg, disp, color = factor(cyl))) + geom_point(size = 2) legend <- get_legend(p_legend) class(legend) ``` `gglegend()` adds a manual legend by drawing an invisible helper layer. ```{r} #| label: gglegend p_base <- ggplot(mtcars, aes(mpg, disp)) + geom_point() legend_data <- data.frame( colour = c("firebrick", "steelblue"), label = c("Group A", "Group B") ) gglegend(aes(colour = label, label = label), legend_data, geom_text, p_base) ``` `set_font()` edits text grobs after a plot has been converted to a gtable. It draws the result and returns the edited grob invisibly. ```{r} #| label: set-font df_text <- data.frame( x = 1:5, y = c(2, 3, 2.5, 4, 3.5), label = LETTERS[1:5] ) p_text <- ggplot(df_text, aes(x, y, label = label)) + geom_text(size = 5) + labs(title = "Edited text grobs") set_font(p_text, family = "serif", fontface = "italic", color = "firebrick") ``` ## Summary The functions in `ggfun` are intentionally small and composable. They are most useful when a plot is almost complete but needs a custom theme element, a specialized layer, a modified facet strip, or access to the data and grobs that `ggplot2` builds internally.