简体   繁体   中英

character string as function argument r

I'm working with dplyr and created code to compute new data that is plotted with ggplot.

I want to create a function with this code. It should take a name of a column of the data frame that is manipulated by dplyr. However, trying to work with columnnames does not work. Please consider the minimal example below:

df <- data.frame(A = seq(-5, 5, 1), B = seq(0,10,1))

library(dplyr)
foo <- function (x) {
         df %>%
            filter(x < 1)
}

foo(B)

Error in filter_impl(.data, dots(...), environment()) : 
  object 'B' not found 

Is there any solution to use the name of a column as a function argument?

If you want to create a function which accepts the string "B" as an argument (as in you question's title)

foo_string <- function (x) {
         eval(substitute(df %>% filter(xx < 1),list(xx=as.name(x))))
}
foo_string("B")

If you want to create a function which accepts captures B as an argument (as in dplyr)

foo_nse <- function (x) {
         # capture the argument without evaluating it
         x <- substitute(x)
         eval(substitute(df %>% filter(xx < 1),list(xx=x)))
}
foo_nse(B)

You can find more information in Advanced R

Edit

dplyr makes things easier in version 0.3. Functions with suffixes "_" accept a string or an expression as an argument

 foo_string <- function (x) {
             # construct the string
             string <- paste(x,"< 1")
             # use filter_ instead of filter
             df %>% filter_(string)
    }
foo_string("B")
 foo_nse <- function (x) {
             # capture the argument without evaluating it
             x <- substitute(x)
             # construct the expression
             expression <- lazyeval::interp(quote(xx < 1), xx = x)
             # use filter_ instead of filter
             df %>% filter_(expression)
    }
foo_nse(B)

You can find more information in this vignette

I remember a similar question which was answered by @Richard Scriven. I think you need to write something like this.

foo <- function(x,...)filter(x,...) 

What @Richard Scriven mentioned was that you need to use ... here. If you type ?dplyr, you will be able to find this: filter(.data, ...) I think you replace .data with x or whatever. If you want to pick up rows which have values smaller than 1 in B in your df, it will be like this.

foo <- function (x,...) filter(x,...)
foo(df, B < 1)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM