On bubbles and trees

Announcing two more guides joining the family.
package
update
Author

Teun van den Brand

Published

December 14, 2024

I now have the awkward pride of announcing a fresh update to an already new package, barely a month after its release. On the one hand I did a little bit of future-proofing, hopefully preventing it from being kicked out of CRAN in the next half year. On the other hand, I also developed a few features that I’m excited to share!

Bubbles

The first thing I’d like to parade around is a new standalone guide for the size aesthetic. The guide_circles() function lets you build a guide that displays the size of points as a series of rings. Simultaneously is source of frustration, but also a neat thing is that this guide uses actual points drawn by the layer glyph function. Taking the correct measurements of points and aligning them was a bit fussy to develop, but at least for circular points, it should work as you’d expect!

Code
library(legendry)
#> Loading required package: ggplot2

gapminder::gapminder |>
  dplyr::filter(year == max(year)) |>
  ggplot(aes(gdpPercap, lifeExp, size = pop, fill = continent)) +
  geom_point(shape = 21) +
  scale_size_area(
    # Note that we need irregular breaks because we scale area, not radius
    limits = c(0, NA), max_size = 20,
    breaks = c(0, 100, 500, 1000)*1e6,
    labels = c(0, "100M", "500M", "1B"),
    guide  = guide_circles(vjust = 1)
  ) +
  scale_x_log10() +
  labs(
    x = "GDP per capita",
    y = "Life expectancy",
    fill = "Continent",
    size = "Population"
  )

I hasten to mention that I’m not the first to develop such a guide, but I think that this is the first version that is implemented as a ggplot2 guide. See scatterpie or mapsf for other implementations.

Trees

The next addition in this release is a guide for dendrograms. There are plenty of better packages to plot dendrograms for the sake of dendrograms, like dendextend. Instead, legendry now has a new scale/guide pair whose job it is to display dendrograms as axis annotations. I’ve personally enjoyed these annotations in combination with heatmaps.

The new scales scale_x_dendro() and scale_y_dendro() accept a <hclust> object generated from the eponymous function. The scale itself just ensure that discrete categories are sorted by the dendrogram order.

It is the guide that comes with these scales, guide_axis_dendro() that does the heavy lifting of actually displaying the dendrogram.

Code
car_cor <- cor(t(mtcars), method = "spearman")
car_clusters <- hclust(as.dist(1 - car_cor))

data <- reshape2::melt(car_cor)

p <- ggplot(data, aes(Var1, Var2, fill = value)) +
  geom_tile() +
  scale_fill_viridis_c() +
  scale_x_dendro(car_clusters, guide = guide_axis_dendro(labels = FALSE)) +
  scale_y_dendro(car_clusters) +
  labs(x = "Cars", y = "Cars", fill = expression(rho^2)) +
  guides(x.sec = guide_axis(angle = 90))

p + coord_fixed()

You may correctly point out that a similar thing already exists in the ggh4x package. The primary difference is that guide_axis_dendro() uses legendry’s gimmicks, such as composed guides. This implies both that it is build on the newer guide system introduced in ggplot2 3.5.0 and that it works well with coord_radial().

Code
ggplot(mtcars, aes(rownames(mtcars), mpg)) +
  geom_col(width = 1) +
  coord_radial(inner.radius = 0.5, expand = FALSE) +
  labs(x = NULL, y = NULL) +
  scale_x_dendro(car_clusters) +
  guides(
    theta = guide_axis_base(angle = 90),
    theta.sec = guide_axis_dendro(labels = FALSE),
    r = "none"
  ) +
  theme(plot.margin = margin(t = 50, b = 50))

In one of the very rare cases that a secondary theta axis can be useful, the dendrogram guide can be placed in the center of polar plots. These shennanigans make it easy to create visualisation like radiating phylogenetic trees.

With all of that wrapped up, all that is left is wishing you all happy holidays!

Session info
si <- sessioninfo::session_info()
# Deidentifying paths on my personal machine
si$packages$library <- NULL
si$platform$pandoc <- NULL
print(si)
#> ─ Session info ───────────────────────────────────────────────────────────────
#>  setting  value
#>  version  R version 4.4.2 (2024-10-31 ucrt)
#>  os       Windows 11 x64 (build 22631)
#>  system   x86_64, mingw32
#>  ui       RTerm
#>  language (EN)
#>  collate  English_Netherlands.utf8
#>  ctype    English_Netherlands.utf8
#>  tz       Europe/Amsterdam
#>  date     2024-12-14
#> 
#> ─ Packages ───────────────────────────────────────────────────────────────────
#>  package     * version  date (UTC) lib source
#>  cli           3.6.3    2024-06-21 []  CRAN (R 4.4.1)
#>  colorspace    2.1-1    2024-07-26 []  CRAN (R 4.4.1)
#>  digest        0.6.37   2024-08-19 []  CRAN (R 4.4.1)
#>  dplyr         1.1.4    2023-11-17 []  CRAN (R 4.4.0)
#>  evaluate      1.0.1    2024-10-10 []  CRAN (R 4.4.1)
#>  fansi         1.0.6    2023-12-08 []  CRAN (R 4.4.0)
#>  farver        2.1.2    2024-05-13 []  CRAN (R 4.4.0)
#>  fastmap       1.2.0    2024-05-15 []  CRAN (R 4.4.0)
#>  gapminder     1.0.0    2023-03-10 []  CRAN (R 4.4.1)
#>  generics      0.1.3    2022-07-05 []  CRAN (R 4.4.0)
#>  ggplot2     * 3.5.1    2024-04-23 []  CRAN (R 4.4.2)
#>  glue          1.8.0    2024-09-30 []  CRAN (R 4.4.1)
#>  gtable        0.3.6    2024-10-25 []  CRAN (R 4.4.1)
#>  htmltools     0.5.8.1  2024-04-04 []  CRAN (R 4.4.0)
#>  htmlwidgets   1.6.4    2023-12-06 []  CRAN (R 4.4.0)
#>  jsonlite      1.8.9    2024-09-20 []  CRAN (R 4.4.1)
#>  knitr         1.49     2024-11-08 []  CRAN (R 4.4.2)
#>  labeling      0.4.3    2023-08-29 []  CRAN (R 4.4.0)
#>  legendry    * 0.2.0    2024-12-14 []  local
#>  lifecycle     1.0.4    2023-11-07 []  CRAN (R 4.4.0)
#>  magrittr      2.0.3    2022-03-30 []  CRAN (R 4.4.0)
#>  munsell       0.5.1    2024-04-01 []  CRAN (R 4.4.0)
#>  pillar        1.9.0    2023-03-22 []  CRAN (R 4.4.0)
#>  pkgconfig     2.0.3    2019-09-22 []  CRAN (R 4.4.0)
#>  plyr          1.8.9    2023-10-02 []  CRAN (R 4.4.0)
#>  R6            2.5.1    2021-08-19 []  CRAN (R 4.4.0)
#>  ragg          1.3.3    2024-09-11 []  CRAN (R 4.4.1)
#>  Rcpp          1.0.13-1 2024-11-02 []  CRAN (R 4.4.2)
#>  reshape2      1.4.4    2020-04-09 []  CRAN (R 4.4.0)
#>  rlang         1.1.4    2024-06-04 []  CRAN (R 4.4.0)
#>  rmarkdown     2.29     2024-11-04 []  CRAN (R 4.4.2)
#>  rstudioapi    0.17.1   2024-10-22 []  CRAN (R 4.4.1)
#>  scales        1.3.0    2023-11-28 []  CRAN (R 4.4.2)
#>  sessioninfo   1.2.2    2021-12-06 []  CRAN (R 4.4.0)
#>  stringi       1.8.4    2024-05-06 []  CRAN (R 4.4.0)
#>  stringr       1.5.1    2023-11-14 []  CRAN (R 4.4.0)
#>  systemfonts   1.1.0    2024-05-15 []  CRAN (R 4.4.0)
#>  textshaping   0.4.1    2024-12-06 []  CRAN (R 4.4.2)
#>  tibble        3.2.1    2023-03-20 []  CRAN (R 4.4.0)
#>  tidyselect    1.2.1    2024-03-11 []  CRAN (R 4.4.0)
#>  utf8          1.2.4    2023-10-22 []  CRAN (R 4.4.0)
#>  vctrs         0.6.5    2023-12-01 []  CRAN (R 4.4.0)
#>  viridisLite   0.4.2    2023-05-02 []  CRAN (R 4.4.0)
#>  withr         3.0.2    2024-10-28 []  CRAN (R 4.4.1)
#>  xfun          0.49     2024-10-31 []  CRAN (R 4.4.1)
#>  yaml          2.3.10   2024-07-26 []  CRAN (R 4.4.1)
#> 
#> 
#> ──────────────────────────────────────────────────────────────────────────────