I want avoid repeating code for plotting, so I wrote a simple function for ggplot. I specify several preferences using theme(). However, if I want to apply an external theme (e.g., theme_bw()), it overrides my specific theme() preferences. If I had been writing code not in a user defined function, the solution would've been simple: rearrange the structure of ggplot's code so that theme_bw() comes before theme(). But I don't know how to address this in the case of a custom function.
Data
df <-
data.frame(
x_names = c("asia", "europe", "america", "africa", "australia"),
y_values = 1:5
)
## x_names y_values
## 1 asia 1
## 2 europe 2
## 3 america 3
## 4 africa 4
## 5 australia 5
Function for plotting
library(ggplot2)
plot_from_data <- function(data_input, x_col, y_col) {
p_barplot <-
ggplot(data = data_input, aes(x = {{ x_col }}, y = {{ y_col }}, fill = as_factor({{ x_col}} ))) +
geom_bar(stat = "identity") +
labs(caption = "caption blah") +
theme(plot.title = element_text(hjust = 0.5, size = 14), ## I have a bunch
axis.text.x=element_text(angle = -60, hjust = 0), ## of preferences
axis.title.x = element_blank(), ## I set up using
legend.title = element_blank(), ## `theme()`
panel.grid = element_blank(),
panel.grid.major=element_blank(),
plot.caption = element_text(hjust = 0, size = 8),
legend.position = "none")
return(p_barplot)
}
Plotting using the function
p <- plot_from_data(data_input = df,
x_col = x_names,
y_col = y_values)
p
But let's say I want to add a theme
p + theme_bw()
Yikes. This is undesired. I didn't want a legend and didn't want x axis title, etc.
So one solution is to go back to plot_from_data's code and add theme_bw() before theme(). But this is not a good solution because I want to be able to flexibly apply different themes on top of plot_from_data's plot, without having to re-edit the function's code for each plot.
Another solution would be to keep both bw_theme() and theme() outside of plot_from_data. Then, for each plot I generate I'd add p + theme_bw() + theme(...). But this is undesired as well because theme() is full of preferences I don't want to repeat each time.
How could I solve this? One idea I have, but don't know how to apply, is having a "theme placeholder" within plot_from_data, before theme(). Something like:
plot_from_data <- function(data_input, x_col, y_col) {
p_barplot <-
ggplot(data = data_input, aes(x = {{ x_col }}, y = {{ y_col }}, fill = as_factor({{ x_col}} ))) +
geom_bar(stat = "identity") +
labs(caption = "caption blah") +
***theme_placeholder*** + ################################## <----------------------- here
theme(plot.title = element_text(hjust = 0.5, size = 14),
axis.text.x=element_text(angle = -60, hjust = 0),
axis.title.x = element_blank(),
legend.title = element_blank(),
panel.grid = element_blank(),
panel.grid.major=element_blank(),
plot.caption = element_text(hjust = 0, size = 8),
legend.position = "none")
return(p_barplot)
}
However, I don't know how to make this flexible enough. One problem I can immediately think of is with ggthemes library that sometimes requires two components for a theme (e.g., theme_economist() and scale_color_economist()).
Any ideas?




