2

For generating a couple of boxplots with the same style, I make identical calls to the boxplot function like in the following minimal example:

boxplot(Petal.Length ~ Species, iris, ylim=c(0,10))
abline(h=8)
legend('topleft',levels(iris$Species))

boxplot(Sepal.Length ~ Species, iris, ylim=c(0,10))
abline(h=8)
legend('topleft',levels(iris$Species))

I would like keep my code readable and maintainable by avoiding code duplication.

Therefore, I thought of using decorators as described in
How customize a plot inside a R function which belong to a package? or
Writing a decorator for R functions or
https://weinstockjosh.com/post/2016-06-08-decorators-in-r/
However, I could not find a way to encapsulate/wrap around the formula used as a parameter in the (box)plot functions, which is beautiful syntactic sugar.

Where could I find a suitable construct offered by R to keep my code readable and maintainable?

NicolasBourbaki
  • 853
  • 1
  • 6
  • 19

3 Answers3

2

Using lapply and reformulate

lapply(c('Petal.Length', 'Sepal.Length'), \(x) {
  boxplot(reformulate(x, 'Species'), iris, ylim=c(0, 10))
  abline(h=8)
  legend('topleft', levels(iris$Species))
})
jay.sf
  • 60,139
  • 8
  • 53
  • 110
1

define function to create boxplot

create_boxplot <- function(data, x_var, y_var, ylim_val, hline_val, legend_pos) {
  ggplot(data, aes_string(x = x_var, y = y_var)) +
    geom_boxplot() +
    ylim(ylim_val) +
    geom_hline(yintercept = hline_val) +
    labs(x = x_var, y = y_var, title = y_var) +
    theme_bw() +
    theme(panel.grid = element_blank()) +
    theme(axis.line = element_line(colour = "black")) +
    theme(legend.position = legend_pos)
}

call function for each variable

create_boxplot(iris, "Species", "Petal.Length", c(0, 10), 8, "topleft")
create_boxplot(iris, "Species", "Sepal.Length", c(0, 10), 8, "topleft")
szmple
  • 453
  • 1
  • 8
1

I found an additional alternative for people facing the same problem:

boxplotCustom <- function (...) {
    boxplot(..., ylim=c(0,10))
    abline(h=8)
    legend('topleft',levels(list(...)[[2]]$Species))
}

boxplot(Petal.Length ~ Species, iris)
boxplot(Petal.Length ~ Species, iris)

I have to admit it's two lines longer than the original solution, but could for example be of advantage when re-using the solution snippet in different files.

NicolasBourbaki
  • 853
  • 1
  • 6
  • 19