-
-
Save z3tt/8b2a06d05e8fae308abbf027ce357f01 to your computer and use it in GitHub Desktop.
library(dplyr) | |
library(forcats) | |
library(ggplot2) | |
library(palmerpenguins) | |
library(ggtext) | |
library(colorspace) | |
library(ragg) | |
url <- "https://raw.githubusercontent.com/allisonhorst/palmerpenguins/master/man/figures/lter_penguins.png" | |
img <- magick::image_read((url)) | |
pic <- grid::rasterGrob(img, interpolate = TRUE) | |
pal <- c("#FF8C00", "#A034F0", "#159090") | |
add_sample <- function(x) { | |
return(c(y = max(x) + .025, | |
label = length(x))) | |
} | |
penguins |> | |
group_by(species) |> | |
mutate(bill_ratio = bill_length_mm / bill_depth_mm) |> | |
filter(!is.na(bill_ratio)) |> | |
ggplot(aes(x = fct_rev(species), y = bill_ratio)) + | |
ggdist::stat_halfeye( | |
aes(color = species, | |
fill = after_scale(lighten(color, .5))), | |
adjust = .5, | |
width = .75, | |
.width = 0, | |
justification = -.4, | |
point_color = NA | |
) + | |
geom_boxplot( | |
aes(color = stage(species, after_scale = darken(color, .1, space = "HLS")), | |
fill = after_scale(desaturate(lighten(color, .8), .4))), | |
width = .42, | |
outlier.shape = NA | |
) + | |
geom_point( | |
aes(color = stage(species, after_scale = darken(color, .1, space = "HLS"))), | |
fill = "white", | |
shape = 21, | |
stroke = .4, | |
size = 2, | |
position = position_jitter(seed = 1, width = .12) | |
) + | |
geom_point( | |
aes(fill = species), | |
color = "transparent", | |
shape = 21, | |
stroke = .4, | |
size = 2, | |
alpha = .3, | |
position = position_jitter(seed = 1, width = .12) | |
) + | |
stat_summary( | |
geom = "text", | |
fun = "median", | |
aes(label = round(after_stat(y), 2), | |
color = stage(species, after_scale = darken(color, .1, space = "HLS"))), | |
family = "Roboto Mono", | |
fontface = "bold", | |
size = 4.5, | |
vjust = -3.5 | |
) + | |
stat_summary( | |
geom = "text", | |
fun.data = add_sample, | |
aes(label = paste("n =", after_stat(label)), | |
color = stage(species, after_scale = darken(color, .1, space = "HLS"))), | |
family = "Roboto Condensed", | |
size = 4, | |
hjust = 0 | |
) + | |
coord_flip(xlim = c(1.2, NA), clip = "off") + | |
annotation_custom(pic, ymin = 2.9, ymax = 3.85, xmin = 2.7, xmax = 4.7) + | |
scale_y_continuous( | |
limits = c(1.57, 3.8), | |
breaks = seq(1.6, 3.8, by = .2), | |
expand = c(.001, .001) | |
) + | |
scale_color_manual(values = pal, guide = "none") + | |
scale_fill_manual(values = pal, guide = "none") + | |
labs( | |
x = NULL, | |
y = "Bill ratio", | |
title = "Bill Ratios of Brush–Tailed Penguins (*Pygoscelis* spec.)", | |
subtitle = "Distribution of bill ratios, estimated as bill length divided by bill depth.", | |
caption = "Gorman, Williams & Fraser (2014) *PLoS ONE* DOI: 10.1371/journal.pone.0090081<br>Visualization: Cédric Scherer • Illustration: Allison Horst" | |
) + | |
theme_minimal(base_family = "Zilla Slab", base_size = 15) + | |
theme( | |
panel.grid.minor = element_blank(), | |
panel.grid.major.y = element_blank(), | |
axis.ticks = element_blank(), | |
axis.text.x = element_text(family = "Roboto Mono"), | |
axis.text.y = element_text( | |
color = rev(darken(pal, .1, space = "HLS")), | |
size = 18 | |
), | |
axis.title.x = element_text(margin = margin(t = 10), | |
size = 16), | |
plot.title = element_markdown(face = "bold", size = 21), | |
plot.subtitle = element_text( | |
color = "grey40", hjust = 0, | |
margin = margin(0, 0, 20, 0) | |
), | |
plot.title.position = "plot", | |
plot.caption = element_markdown( | |
color = "grey40", lineheight = 1.2, | |
margin = margin(20, 0, 0, 0)), | |
plot.margin = margin(15, 15, 10, 15) | |
) |
Thanks for your feedback @francisvolh 🙌
cf. warning fonts:
Exactly, the fonts need to be installed locally. All font files are available via GoogleFonts:
https://fonts.google.com/specimen/Zilla+Slab
https://fonts.google.com/specimen/Roboto+Condensed
https://fonts.google.com/specimen/Roboto+Mono
cf. warning element_text:
Yes, vectorized inputs are not supported for theme elements but work! The warning means the resulting behavior is not guaranteed and the trick might stop working at some point in future. I use it here to color the labels on the y-axis -- it doesn't matter if you use the darken
function or not, the warning pops up because we feed a vector to the color argument. Just passing c("red", "green", "blue")
would cause the same warning, while setting a single color e.g. "black"
does not.
cf. namespace:
Hm, interesting. As I rarely use namespace convention when using ggplot2, I've never run into this issue. You mean when specifying ggplot2::aes(color = ggplot2::stage(species, after_scale = colorspace::darken(color, .1, space = "HLS"))))
, ggplot can't find the species column? There is a related issue on the ggplot2 repo, maybe this helps: tidyverse/ggplot2#6104.
Thanks for the comments @z3tt! And thanks a lot also for the input on my warnings/bullet points!
I checked the thread cf. namespace and it got a bit complicated for me to understand the idea of stage not being a proper function but I guess I can just avoid using "stage" and go on with my life for life! But you were on point, if no loading the library, and specifying ggplot2::stage
and it seems expected from the issue you linked me to.... and I think they dont want or thinkg is something to be fixed (as stage
seems not to be a proper function).
Cheers! and thanks again!
Tbh that discussion is also beyond me 🤓 Exactly, you can use the logic without stage()
by repeating the aesthetic, e.g.
geom_point(
aes(color = species,
color = after_scale(darken(color, .1, space = "HLS")))
)
It's not the official way to do it and you'll get a warning but it works perfectly fine and I often do it myself. Just trying to avoid spreading the unofficial approach in my workshops and tutorials.
PS: However, you might run into the same issue when using the after_scale()
function without loading {ggplot2} because it's not considered a "true function" as well.
Hi Cédric, thanks for the awesome work! I have been able to use it for some plots I wanted to make. Thanks!!
I have a couple of quick questions for you though. First of all I get a few warnings (some are font related, which are not supported on my Windows database, so very unimportant) and one is
'1: Vectorized input to
element_text()
is not officially supported.'And I think it may come from line 99
color = rev(darken(pal, .1, space = "HLS"))
, because if I comment out thataxis.text.y =
warning goes away.Also, I am trying to avoid loading libraries in all my scripts, and just calling the function from the library like
ggplot2::ggplot()
. If I do this, theggplot2::stage
in thegeom_boxplot
(or any other stage) does not recognize the species as an object, on line 35 for example. If I simply definecolor = species
(with no stage, it works.I guess this is all unimportant! but I wondered if you hade any comments about this! thanks!
ps: I have a forked gist of what I have done if you have a minute to see it here