How to use a variable to specify column name in ggplot

前端 未结 6 1379
别那么骄傲
别那么骄傲 2020-11-22 03:41

I have a ggplot command

ggplot( rates.by.groups, aes(x=name, y=rate, colour=majr, group=majr) )

inside a function. But I would like to be a

6条回答
  •  名媛妹妹
    2020-11-22 04:36

    From the release notes of ggplot2 V3.0.0 :

    aes() now supports quasiquotation so that you can use !!, !!!, and :=. This replaces aes_() and aes_string() which are now soft-deprecated (but will remain around for a long time).

    The idiomatic way now would be to convert to a symbol the string that the variable contains, using sym()(which is almost the same as base aliases as.name() / as.symbol()), and unquote it using !!

    Simulating OP's data we can do :

    library(tidyverse)
    rates.by.groups <- data.frame(
      name = LETTERS[1:3],
      rate = 1:3,
      mjr = LETTERS[c(4,4,5)],
      gender = c("M","F","F")
    )
    
    f <- function(column) {
      column <- sym(column)
      ggplot(rates.by.groups, 
             aes(x = name, 
                 y = rate, 
                 fill  = !!column, 
                 group = !!column)) +
        geom_col()
    }
    
    f("gender")
    f("mjr")
    x <- "gender"
    f(x)
    

    If we'd rather feed raw names to the function we can do:

    f2 <- function(column) {
      column <- ensym(column)
      ggplot(rates.by.groups, 
             aes(x = name, 
                 y = rate, 
                 fill  = !!column, 
                 group = !!column)) +
        geom_col()
    }
    

    It will work with names a.k.a. symbols AND with string literals

    f2(gender)
    f2(mjr)
    f2("gender")
    f2("mjr")
    

    As Lionel says about ensym():

    it's meant to mimic the syntax of arguments where you can supply both in the LHS, e.g. list(bare = 1, "quoted" = 2)


    A note on enquo()

    enquo()quotes the expression (not necessarily a symbol) fed to the argument, it doesn't convert a string literal to a symbol as ensym() does so it might be less adapted here, but we can do :

    f3 <- function(column) {
      column <- enquo(column)
      ggplot(rates.by.groups, 
             aes(x = name, 
                 y = rate, 
                 fill  = !!column, 
                 group = !!column)) +
        geom_col()
    }
    
    f3(gender)
    f2(mjr)
    

提交回复
热议问题