Accessing variable attribute information for axis labels in a ggplot2 function

Viewed 309

I am looking for ways to increase data vis efficiency for a large dataset. I have created several functions using ggplot2 to that end. Some of the resulting figures may be for distribution, consequently, I'd like them to have comprehendible titles and axis labels. I'm thinking I can associate readable labels to each variable using attr(). This way I do not have to rename the variables and deal with long variable names including spaces. I have succeeded in this when using ggplot's functions

library(ggplot2)
library(magrittr)

# Set attributes
mt <- mtcars
attr(mt$mpg, "desc") <- "Miles per Gallon"   
attr(mt$cyl, "desc") <- "Number of Cylinders"


mt %>% 
  ggplot() +
  geom_point(aes(x = cyl, y = mpg)) +
  labs(x = attr(mt$cyl, "desc"),
       y = attr(mt$mpg, "desc"))

The above code behaves as I expect and returns a graph containing axis labels. However, when I create a graphing function I can not figure out how to access the variable attributes. Both of the following attempts succeed in creating the graph, however do not produce the axis labels

vis_1 <- function(.data, .x, .y) {
  .data %>% 
    ggplot() + 
    geom_point(aes(x = {{.x}}, y = {{.y}})) +
    labs(x = attr({{.data$.x}}, "desc"),
         y = attr({{.data$.y}}, "desc"))
}

vis_1(.data = mt, .x = cyl, .y = mpg)

and

vis_2 <- function(.data, .x, .y) {
  attr_x <- attr(.data$.x, "desc")
  attr_y <- attr(.data$.y, "desc")
  
  .data %>% 
    ggplot() + 
    geom_point(aes(x = {{.x}}, y = {{.y}})) +
    labs(x = attr_x,
         y = attr_y)
}

vis_2(.data = mt, .x = cyl, .y = mpg)

Any suggestions would be appreciated.

1 Answers

The problem here is quoting of the variables you are passing.

One option if you are willing to use cyl and mpg as quoted variables. The base [ subset inside of attr will work fine, and in ggplot you can use !!sym().

vis_2 <- function(df, x, y) {
  
  attr_x <- attr(df[,x], "desc")
  attr_y <- attr(df[,y], "desc")
  
  df %>% 
    ggplot() + 
    geom_point(aes(!!sym(x), !!sym(y))) +
    labs(x = attr_x,
         y = attr_y)
}

vis_2(mt, 'cyl', 'mpg')

A version passing unquoted variables. This solution uses deparse(substitute(x)) for use in the [ call and !!enquo(x) for use in ggplot.


vis_3 <- function(df, x, y) {
  
  # base quoting
  x_sub <- deparse(substitute(x))
  y_sub <- deparse(substitute(y))
  
  attr_x <- attr(df[,x_sub], "desc")
  attr_y <- attr(df[,y_sub], "desc")
  
  df %>% 
    ggplot() + 
    geom_point(aes(!!enquo(x), !!enquo(y))) +
    labs(x = attr_x,
         y = attr_y)
}


vis_3(mt, cyl, mpg)

Yet another version using unquoted variables, this one using {{ for ggplot and deparse(ensym() for [.

vis_4 <- function(df, x, y) {
  
  attr_x <- attr(df[,deparse(ensym(x))], "desc")
  attr_y <- attr(df[,deparse(ensym(y))], "desc")
  
  df %>% 
    ggplot() + 
    geom_point(aes({{x}}, {{y}})) +
    labs(x = attr_x,
         y = attr_y)
}


vis_4(mt, cyl, mpg)
Related