ggh4x

repository·main·Indexed 20 days ago

https://github.com/teunbrand/ggh4x

A ggplot2 extension package providing utility functions for advanced plot customization. Key features include nested facets (facet_nested, facet_nested_wrap), extended facet wraps and grids (facet_wrap2, facet_grid2), per-panel position scales (facetted_pos_scales), custom panel sizing (force_panelsizes), and support for multiple color scales (scale_colour_multi). It also provides statistical layers for theoretical densities, rolling kernels, and group-wise transformations.

Tokens
3.3K
Snippets
11
Records
12
Agent score
22%

What's inside ggh4x

  1. Overview of ggh4x features

    main

    The ggh4x package is an extension for ggplot2 that provides utility functions for advanced plot tweaking that fall outside the standard 'grammar of graphics'.

    Key capabilities include:

    Facet Customization

    • Extended Facets: Additional options for axis labelling and placement.
    • Nested Facets: Strips that can span multiple panels.
    • Manual Facets: Custom layouts.
    • Custom Strips: More types of strips for facet labels.
    • Per-panel Position Scales: Adjusting scales on a per-panel basis.
    • Panel Sizing: Varying the size of panels without being limited by global aspect.ratio or fixed coordinates.

    Statistical Layers

    • Theoretical Densities: Overlaying densities computed with the fitdistrplus package.
    • Rolling Kernels: Drawing trend lines using a rolling kernel.
    • Group-wise Transformations: Transforming x and y positions in a group-wise manner.
    • Run-length Encoding: Calculating run-length encodings of data.
  2. Install ggh4x

    main

    You can install the stable version of ggh4x from CRAN or the development version from GitHub.

    From CRAN:

    install.packages("ggh4x")

    From GitHub (Development version):

    # install.packages("devtools")
    devtools::install_github("teunbrand/ggh4x")
    install.packages("ggh4x")
  3. Adjust panel sizes with force_panelsizes

    main

    Use force_panelsizes() to set the dimensions of panels individually, allowing for non-uniform panel sizes without relying on a global aspect.ratio.

    Example:

    # Define desired column sizes
    size <- 2 / (1 + sqrt(5))
    g <- g + force_panelsizes(cols = c(1, size, size ^ 2), respect = TRUE)
    size <- 2 / (1 + sqrt(5))
    g <- g + force_panelsizes(cols = c(1, size, size ^ 2), respect = TRUE)
  4. Set individual position scales with facetted_pos_scales

    main

    You can specify different position scales (like x or y axes) for each panel individually using facetted_pos_scales(). The scales in the provided list must be in the same order that the facets appear in the plot.

    Example:

    position_scales <- list(
      scale_x_reverse(guide = guide_axis(minor.ticks = TRUE)),
      scale_x_continuous(labels = dollar, guide = guide_axis(cap = "both")),
      scale_x_continuous(breaks = c(3, 4), expand = c(0,0))
    )
    
    g <- g + facetted_pos_scales(x = position_scales)
    position_scales <- list(
      scale_x_reverse(guide = guide_axis(minor.ticks = TRUE)),
      scale_x_continuous(labels = dollar, guide = guide_axis(cap = "both")),
      scale_x_continuous(breaks = c(3, 4), expand = c(0,0))
    )
    
    g <- g + facetted_pos_scales(x = position_scales)
  5. Configure nested facets with facet_nested

    main

    Use facet_nested() to create facets where duplicated strip labels are merged into a single strip. This is useful for hierarchical grouping.

    Example:

    g <- g + 
      facet_nested(~ Nester + Species, scales = "free", nest_line = TRUE)
    g <- g + 
      facet_nested(~ Nester + Species, scales = "free",
                   nest_line = TRUE)
  6. Use scale_colour_multi for multiple colour scales

    main

    To use multiple colour scales in a single plot, you must first map data to 'alternative aesthetics' (custom names) within your geom_* layers. scale_colour_multi then maps these custom aesthetics to specific colour palettes.

    Note: ggplot2 will issue warnings about 'unknown aesthetics' when you use custom names like SW or PL; this is expected behavior.

    Arguments provided as lists to scale_colour_multi are passed on to individual scales.

    library(ggh4x)
    library(scales)
    
    df <- transform(iris, Nester = ifelse(Species == "setosa", "Short Leaves", "Long Leaves"))
    
    g <- ggplot(df, aes(Sepal.Width, Sepal.Length)) +
      theme_classic() +
      theme(strip.background = element_blank())
    
    # 1. Map data to alternative aesthetics (e.g., SW, PL, PW)
    g <- g + 
      geom_point(aes(SW = Sepal.Width), data = ~ subset(., Species == "setosa")) +
      geom_point(aes(PL = Petal.Length), data = ~ subset(., Species == "versicolor")) +
      geom_point(aes(PW = Petal.Width), data = ~ subset(., Species == "virginica"))
    
    # 2. Apply the multi-colour scale
    g <- g +
      scale_colour_multi(
        aesthetics = c("SW", "PL", "PW"),
        name = list("Blue", "Pink", "Orange"),
        colours = list(
          brewer_pal(palette = "YlGnBu")(6),
          brewer_pal(palette = "RdPu")(6),
          brewer_pal(palette = "YlOrRd")(6)
        ),
        guide = guide_colorbar(barheight = unit(50, "pt"))
      )
    
    g
  7. Use extended facet wrap with facet_wrap2()

    main

    The facet_wrap2() function extends ggplot2::facet_wrap() by providing more control over axis placement and labels in inner facets.

    Key arguments:

    • axes: Allows drawing axes at inner facets. Use values like "all" to show axes on all inner facets.
    • remove_labels: Allows omitting axis labels while keeping ticks. For example, setting remove_labels = "x" will remove the x-axis labels from inner facets but keep the ticks.
    p <- ggplot(mpg, aes(displ, hwy, colour = as.factor(cyl))) + geom_point()
    
    # Show axes on all inner facets but remove x-axis labels
    p + facet_wrap2(vars(class), axes = "all", remove_labels = "x")
  8. Customize individual facet scales with facetted_pos_scales()

    main

    The facetted_pos_scales() function allows you to specify unique scales (labels, breaks, limits, transformations, or guides) for each individual facet panel.

    Usage Requirements:

    • The list of scales must follow the order of the facets (assuming scales are set to 'free').
    • This function must be called after the facets have been added to the ggplot object.

    Important Limitation: Because scale transformations are applied after stat calculations when using facetted_pos_scales(), it can cause issues with layers using non-identity statistics (like geom_density()). For such layers, it is recommended to pre-transform the data in the aes() mapping.

    # Define a list of scales for each facet
    scales <- list(
      scale_x_reverse(),
      scale_x_continuous(labels = scales::dollar, minor_breaks = c(2.5, 4.5)),
      scale_x_continuous(breaks = c(2.945, 6), limits = c(0, 10), guide = "axis_minor")
    )
    
    # Apply to the plot after adding facets
    ggplot(mpg, aes(displ, hwy)) +
      geom_point() +
      facet_wrap(vars(drv), scales = "free_x") +
      facetted_pos_scales(x = scales)
  9. Set specific panel sizes with force_panelsizes()

    main

    The force_panelsizes() function allows you to set absolute or relative sizes for facet rows and columns. This is useful for creating layouts where panels have specific dimensions (e.g., placing a density plot next to a scatter plot).

    Key features:

    • Overriding: These settings overrule coordinates' aspect ratios, theme aspect ratios, and space = "free" facet arguments.
    • Relative vs Absolute:
      • By default, rows and columns are relative within themselves.
      • Setting respect = TRUE makes the relative units consistent across both rows and columns.
      • You can use grid::unit() to specify absolute sizes.
    • Requirement: Must be added after any facets.
    # Set columns to relative sizes 1 and 0.2, and rows to 0.5, respecting aspect ratio
    g <- ggplot(faithful) +
      geom_point(aes(waiting, eruptions), data = cbind(faithful, facet = "Points")) +
      geom_density(aes(y = eruptions), data = cbind(faithful, facet = "Density")) +
      facet_grid(~ facet, scales = "free_x") +
      force_panelsizes(cols = c(1, 0.2), 
                       rows = c(0.5), 
                       respect = TRUE)
  10. Create nested facets with facet_nested()

    main

    The facet_nested() function allows for hierarchical facet strips where outer strips can span multiple inner strips belonging to the same category. This is useful for representing hierarchical relationships in data.

    Key features:

    • Nesting lines: You can indicate hierarchy using lines instead of background strips by setting nest_line = TRUE. The appearance is controlled by the theme element ggh4x.facet.nestline.
    • Data flexibility: Unlike facet_grid(), facet_nested() does not require the input data to contain all facet variables.
    • Strip ordering: When strips are placed at the bottom (using switch = "x"), facet_nested() rearranges them so inner strips are closest to the panels and spanning strips are furthest away.
    # Basic nested facets
    ggplot(df, aes(Sepal.Width, Sepal.Length)) +
      geom_point() +
      facet_nested(~ Nester + Species)
    
    # Nested facets with lines and custom theme
    ggplot(df, aes(Sepal.Width, Sepal.Length)) +
      geom_point() +
      facet_nested(~ Nester + Species, nest_line = TRUE) +
      theme(strip.background = element_blank(),
            ggh4x.facet.nestline = element_line(colour = "blue"))
  11. Use extended facet grid with facet_grid2()

    main

    The facet_grid2() function extends ggplot2::facet_grid() with enhanced axis control and 'independent' scales.

    Key arguments:

    • axes: Controls axis placement at inner facets (e.g., axes = "all").
    • remove_labels: Controls which axis labels to omit (e.g., remove_labels = "y").
    • independent: Allows scales to be free within rows and columns of the layout, rather than just between rows or columns. For example, independent = "x" allows scales to be free within columns.

    Note on constraints: You cannot use independent scales and space = "free" for the same dimension. However, you can combine them if they apply to different dimensions (e.g., independent = "y" and space = "free_x").

    p <- ggplot(mpg, aes(displ, hwy, colour = as.factor(cyl))) + geom_point()
    
    # Use independent x scales and show axes on all inner facets
    p + facet_grid2(vars(drv), vars(year), axes = "all", remove_labels = "y")
    
    # Use independent x scales with free x space (not allowed) vs independent y with free x space (allowed)
    p + facet_grid2(vars(drv), vars(year), scales = "free", independent = "y", space = "free_x")
  12. Create nested facet wraps with facet_nested_wrap()

    main

    The facet_nested_wrap() function provides a nested version of facet_wrap(). It supports spanning strips for any strip.position and includes a bleed argument to merge adjacent strips that belong to the same category.

    Key arguments:

    • bleed: When TRUE, it merges adjacent strips in the layout if they belong to the same category.
    • axes: Can be used to duplicate axes or just axis ticks.
    • remove_labels: Can be used to remove labels for specific positions like "rows".
    ggplot(mpg, aes(displ, hwy)) +
      geom_point() +
      facet_nested_wrap(vars(cyl, drv), dir = "v",
                        strip.position = "left",
                        axes = "full",
                        remove_labels = "rows",
                        bleed = TRUE)