строка символов в качестве аргумента функции r

Я работаю с dplyr и создал код для вычисления новых данных, которые отображаются с помощью ggplot.

Я хочу создать функцию с этим кодом. Он должен принимать имя столбца фрейма данных, которым управляет dplyr. Однако попытка работать с именами столбцов не работает. Пожалуйста, рассмотрите минимальный пример ниже:

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 

Есть ли решение использовать имя столбца в качестве аргумента функции?


person jnshsrs    schedule 23.09.2014    source источник
comment
Не могли бы вы сделать свой вопрос воспроизводимым? На данный момент вы даете фрейм данных со всеми (двумя) значениями выше 1.   -  person Jaap    schedule 23.09.2014
comment
Спасибо Jaap за совет, я отредактировал df, чтобы обеспечить воспроизводимость   -  person jnshsrs    schedule 23.09.2014
comment
Я помню похожий вопрос, на который ответил @Richard Scriven. Я думаю, вам нужно написать что-то вроде foo <- function(x,...)filter(x,...) У меня сейчас есть следующее. Не уверен, что пишу что-то правильное. Но результат кажется правильным.foo <- function (x,...) filter(x,...);foo(df, B < 1)   -  person jazzurro    schedule 23.09.2014
comment
@jazzurro, к сожалению, я не могу воспроизвести твои советы. Может быть, вы можете привести воспроизводимый пример.   -  person jnshsrs    schedule 23.09.2014
comment
@jnshsrs Я использовал ваш df и запустил код. R возвращает первую строку. Не могли бы вы запустить код с вашим df на вашем компьютере?   -  person jazzurro    schedule 23.09.2014
comment
@jazzurro, хорошо, я могу запустить код. Я пытаюсь реализовать это в своей функции и дать отзыв о результате. Спасибо!   -  person jnshsrs    schedule 23.09.2014
comment
@jnshsrs Хорошо, я рад это слышать. Тогда я оставлю свой комментарий в качестве ответа.   -  person jazzurro    schedule 23.09.2014


Ответы (2)


Если вы хотите создать функцию, которая принимает строку «B» в качестве аргумента (как в заголовке вашего вопроса)

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

Если вы хотите создать функцию, которая принимает захваты B в качестве аргумента (как в 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)

Дополнительную информацию можно найти в разделе Advanced R.

Редактировать

dplyr упрощает работу в версии 0.3. Функции с суффиксом "_" принимают в качестве аргумента строку или выражение.

 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)

Дополнительную информацию можно найти в этой винье.

person Matthew    schedule 23.09.2014
comment
Спасибо за эту дополнительную информацию. Это очень полезно для меня. - person jnshsrs; 24.09.2014

Я помню похожий вопрос, на который ответил @Richard Scriven. Я думаю, что вам нужно написать что-то вроде этого.

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

@Richard Scriven упомянул, что здесь нужно использовать .... Если вы наберете ?dplyr, вы сможете найти это: filter(.data, ...) Думаю, вы заменили .data на x или что-то в этом роде. Если вы хотите выбрать строки со значениями меньше 1 в B в вашем df, это будет так.

foo <- function (x,...) filter(x,...)
foo(df, B < 1)
person jazzurro    schedule 23.09.2014
comment
Должно быть, я старею. Я не помню этого. Но +1, потому что это работает! - person Rich Scriven; 23.09.2014
comment
@RichardScriven Я могу ошибаться. Но, я думаю, именно вы ответили на аналогичный вопрос, используя select(). Это было моим вдохновением. Приведенный выше код работает, но я был удивлен, когда увидел это. - person jazzurro; 24.09.2014