Daniel V
Daniel V

Reputation: 1388

Optional aesthetic in ggplot2

I'm trying to build a generalised function for a dashboard. The user can enter a character value to represent the colour aesthetic, but if it's NA then none is done.

When !is.na(input) the behaviour should be the same as

ggplot(data, aes_string(x = "Date", colour = input)) +
    geom_density()

Otherwise it should be the same as

ggplot(data, aes_string(x = "Date")) +
    geom_density()

Is there a way of doing this that doesn't require me to split my entire codeset in two?

Upvotes: 1

Views: 251

Answers (2)

eipi10
eipi10

Reputation: 93761

You could set the default colour argument to NULL, which will make it optional. For example:

library(tidyverse)
theme_set(theme_bw())

pfnc = function(data, x, colour=NULL) {
  ggplot(data, aes_string(x=x, colour=colour)) +
    geom_density()
}

pfnc(mtcars, "hp")
pfnc(mtcars, "hp", "factor(cyl)")
pfnc(iris, "Petal.Width")
pfnc(iris, "Petal.Width", "Species")

enter image description here

Another option is to use the ... argument, which allows the use of arbitrary aesthetic mappings:

pfnc = function(data, x, ...) {
  ggplot(data, aes_string(x=x, ...)) +
    geom_density()
}

pfnc(iris, "Petal.Width")
pfnc(iris, "Petal.Width", colour="Species", fill="Species")
pfnc(midwest, "popdensity", colour="state", linetype="factor(inmetro)") +
  scale_x_log10()

enter image description here

aes_string is only "soft-deprecated" so it will be around for a while. But if you want to avoid aes_string, you could use tidy evaluation. This takes a bit more work and also can't directly take an expression string (e.g., "factor(cyl)") as an argument (though there are probably ways to make that work too).

pfnc = function(data, x, colour=NULL) {
  
  x = as.name(x)
  if(!is.null(colour)) {
    colour=as.name(colour)
  }
  
  ggplot(data, aes(x={{x}}, colour={{colour}})) +
    geom_density()
}

pfnc(mtcars, "hp")
pfnc(mtcars %>% mutate(cyl=factor(cyl)), "hp", "cyl")

Upvotes: 4

Ronak Shah
Ronak Shah

Reputation: 388817

You can write a function and pass aesthetic as an argument in the function. aes_string has been deprecated, you can use .data pronoun now.

Using @Ian Campbell's data.

library(ggplot2)

mtcars$cyl <- as.factor(mtcars$cyl)

optional_aes <- function(df, color = NA) {
  p <- ggplot(df, aes(mpg)) + geom_density()
  if(!is.na(color)) p <- p + aes(color = .data[[color]])
  p
}

optional_aes(mtcars)

enter image description here

optional_aes(mtcars, "cyl")

enter image description here

Upvotes: 3

Related Questions