How to use a variable to specify column name in ggplot

前端 未结 6 1377
别那么骄傲
别那么骄傲 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:21

    You can use aes_string:

    f <- function( column ) {
        ...
        ggplot( rates.by.groups, aes_string(x="name", y="rate", colour= column,
                                            group=column ) )
    }
    

    as long as you pass the column to the function as a string (f("majr") rather than f(majr)). Also note that we changed the other columns, "name" and "rate", to be strings.

    If for whatever reason you'd rather not use aes_string, you could change it to (the somewhat more cumbersome):

        ggplot( rates.by.groups, aes(x=name, y=rate, colour= get(column),
                                            group=get(column) ) )
    
    0 讨论(0)
  • 2020-11-22 04:27

    Using aes_string does fix this problem, but does face an issue when adding error bars geom_errorbar. Below is a simple solution.

    #Identify your variables using the names of your columns indie your dataset
     xaxis   <- "Independent"   
     yaxis   <- "Dependent"
     sd      <- "error"
    
    #Specify error bar range (in 'a-b' not 'a'-'b')
     range   <- c(yaxis, sd)                                #using c(X, y) allows use of quotation marks inside formula
     yerrbar <- aes_string(ymin=paste(range, collapse='-'), 
                           ymax=paste(range, collapse='+'))
    
    
    #Build the plot
      ggplot(data=Dataset, aes_string(x=xaxis, y=yaxis)) +
        geom_errorbar(mapping=yerrbar, width=15, colour="#73777a", size = 0.5) +
        geom_point   (shape=21)
    

    Bonus, you can also add facets to your plot using these lines inside the ggplot:

    facet_grid(formula(paste(Variable1, "~", Variable2)))
    

    This script was modified from this original post: ggplot2 - Error bars using a custom function

    0 讨论(0)
  • 2020-11-22 04:29

    Another option (ggplot2 > 3.0.0) is to use the tidy evaluation pronoun .data to slice the chosen variable/column from the rates.by.groups data frame.

    library(ggplot2)
    theme_set(theme_classic(base_size = 14))
    
    # created by @Moody_Mudskipper
    rates.by.groups <- data.frame(
      name = LETTERS[1:3],
      rate = 1:3,
      mjr = LETTERS[c(4, 4, 5)],
      gender = c("M", "F", "F")
    )
    
    f1 <- function(df, column) {
      gg <- ggplot(df, 
             aes(x = name, 
                 y = rate, 
                 fill  = .data[[column]], 
                 group = .data[[column]])) +
        geom_col() +
        labs(fill = column)
      return(gg)
    }
    
    plot_list <- lapply(list("gender", "mjr"), function(x){ f1(rates.by.groups, x) })
    plot_list
    #> [[1]]
    

    #> 
    #> [[2]]
    

    # combine all plots
    library(egg)
    ggarrange(plots = plot_list,
              nrow = 2,
              labels = c('A)', 'B)'))
    

    Created on 2019-04-04 by the reprex package (v0.2.1.9000)

    0 讨论(0)
  • 2020-11-22 04:34

    Here's an extremely simple way!

    Do these two things:

    1. Turn the column name into a symbol with sym()
    2. Add !! when you use it

    Minimal Reproducible Example:

    my_col <- sym("Petal.Length")
    
    iris %>% 
      ggplot(aes(x = Sepal.Length, y = !!my_col)) +
      geom_point()
    
    0 讨论(0)
  • 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)
    
    0 讨论(0)
  • 2020-11-22 04:38

    Try using aes_string instead of aes.

    0 讨论(0)
提交回复
热议问题