Нестандартная оценка состояния даты с функцией фильтра - PullRequest
0 голосов
/ 24 января 2019

Я пытаюсь использовать dplyr::filter() с NSE, но не могу заставить его работать, когда отфильтрованная переменная as.Date().

Вот функция, которая почти работает:

foo <- function(d, f, var) {
  d %>% 
    filter_(paste0(var, ">=", f))
}

d <- data.frame(a=1:10, b=1)
foo(d, f=5, var="a")
#    a b
# 1  5 1
# 2  6 1
# 3  7 1
# 4  8 1
# 5  9 1
# 6 10 1

Но если a - дата, она не будет работать:

d <- data.frame(a=seq.Date(as.Date("2019-01-01"), length.out = 7, by="day"), b=1)

foo(d, f=as.Date("2019-01-05"), var="a") # or foo(d, f="2019-01-05", var="a")
#            a b
# 1 2019-01-01 1
# 2 2019-01-02 1
# 3 2019-01-03 1
# 4 2019-01-04 1
# 5 2019-01-05 1
# 6 2019-01-06 1
# 7 2019-01-07 1

Также я пытался с этим:

foo2 <- function(d, f, var) {
  d %>% 
    filter(!!var >= f)
}
#foo2(d, f=5, var="a")
#foo2(d, f="2019-01-05", var="a")

Что не работает ни в одном из случаев, мне интересно знать также, почему foo2 не работает.

Ответы [ 3 ]

0 голосов
/ 24 января 2019

попробуйте передать аргумент var не как строку.в этом случае вам нужно изменить функцию foo на:

foo <- function(d, f, var) {
   var <- enquo(var)
   d %>% 
      filter(!!var >= f)
}
foo(d, f=as.Date("2019-01-05"), var=a)
0 голосов
/ 24 января 2019

Не пересматривайте свою функцию.Давайте сосредоточимся на коде

foo(d, f = as.Date("2019-01-05"), var = "a")

Если вход f равен Date, оператор paste0(var, ">=", f) в вашей функции вернет

"a >= 2019-01-05" (Это означает, что столбец a больше и равен "2019-01-05", который является символьной строкой, а не датой, поскольку выходные данные paste() всегда являются символами)

Вышеприведенное утверждение не имеет смысла, потому что строки символов невозможно сравнить.Таким образом, вам необходимо преобразовать дату ввода в числовое значение unclass() или as.numeric(), например

foo(d, f = unclass(as.Date("2019-01-05")), var = "a")

, и оператор вернет "a >= 17901", что является нормальным логическимоператор.


Вывод

foo(d, f = unclass(as.Date("2019-01-05")), var = "a")

#            a b
# 1 2019-01-05 1
# 2 2019-01-06 1
# 3 2019-01-07 1

Обратите внимание, что "a> = 17901" будет успешным, поскольку даты (столбец a)) можно сравнить с цифрами (17910).

0 голосов
/ 24 января 2019

Вам не нужно !! (rlang::). Заключите var в as.name (или as.symbol), чтобы превратить в символ, а затем используйте eval() внутри filter, чтобы оценить объект в функциональной среде:

library(magrittr)
library(dplyr)    

d <- data.frame(a=seq.Date(as.Date("2019-01-01"), length.out = 7, by="day"), b=1)

foo2 <- function(d, f, var) {
  sym <- as.name(var)

  d %>% 
    filter(eval(sym) >= f)
}

Результат:

> foo2(d, f="2019-01-05", var="a")
           a b
1 2019-01-05 1
2 2019-01-06 1
3 2019-01-07 1
...