Hi there!
My question has to do with writing a custom wrapper for ggplot2
. I should say that I've posted this question first at Stack Overflow but unfortunately it was closed because deemed as opinion-based.
In short, I want to understand whether there's a conventional way to program optional arguments for a function that wraps ggplot()
. Although I've come up with a solution that does work (see below), I'm afraid it's not t nicely scalable if I want to allow greater diversity in terms of what can be tweaked in my wrapper.
For example, I want to build a function that plots a bar chart. I'd like to allow, for example, (1) the ability to either have errrorbars or not, (2) to either have bar labels show raw values or display a transformation (e.g., percentages), (3) allow the user provide a set of alternative values for x axis labels, and (4) decide whether bars should be ordered from highest to lowest or not.
So I tried achieving this with code such as this one:
library(ggplot2)
library(tidyselect)
bar_chart <- function(data, x_var, y_var, reorder_cols = TRUE, x_axis_labels = NULL, add_errorbar = NULL, show_in_percents) {
reordered <- geom_bar(stat = "identity", width = 0.8, aes(x = reorder({{ x_var }}, -{{ y_value }} ), y = {{ y_value }}, fill = as_factor({{ x_var }})))
not_reordered <- geom_bar(stat = "identity", width = 0.8, aes(x = {{ x_var }}, y = {{ y_value }}, fill = as_factor({{ x_var }})))
with_x_axis_labels <- scale_x_discrete(labels = setNames(str_wrap(x_axis_labels, 10), names(x_axis_labels)), expand = c(0, 0))
without_x_axis_labels <- scale_x_discrete(expand = c(0, 0))
if (reorder_cols == TRUE) {
my_geom_bar <- reordered
} else {
my_geom_bar <- not_reordered
}
if (is.null(x_axis_labels)) {
my_scale_x_discrete <- without_x_axis_labels
} else {
my_scale_x_discrete <- with_x_axis_labels
}
if (add_errorbar == TRUE) {
my_errorbar <- geom_errorbar(aes(x = {{ x_var }}, y = {{ y_value }}, ymin = errorbar_lwr, ymax = errorbar_upr), width = 0.1, size = 0.75)
} else {
my_errorbar <- NULL
}
if (show_in_percents == TRUE) {
my_bar_label_percent_or_raw <- paste0(100*round({{ y_value }}, 2), "%")
} else if (show_in_percents == FALSE) {
my_bar_label_percent_or_raw <- round({{ y_value }}, 2)
}
ggplot(data) +
my_geom_bar +
my_errorbar +
my_scale_x_discrete +
geom_text(
aes(
x = {{ x_var }},
y = {{ y_value }},
label = my_bar_label_percent_or_raw,
vjust = 1.5
),
color = "white",
size = 6,
fontface = "bold"
)
}
But such code seems clunky, because what if I wanted to allow my bar_chart()
wrapper to accept more tweaking options? One can think of many more: adding caption, changing font, text size, colors, etc. I've tried googling blogs and such, and only found this, which is still not giving me the answers I'm looking for.
So my bottom-line question is whether there's a conventional/mainstream way to program optional arguments when creating wrappers for ggplot()
. I hope this question is considered on-topic here.
Thank you!