首页 > 解决方案 > 具有过滤功能的日期条件的非标准评估

问题描述

我正在尝试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它为什么不起作用。

标签: rdplyrnse

解决方案


不要修改你的功能。让我们专注于代码

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

如果输入f是 a Date,则函数中的语句paste0(var, ">=", f)将返回

"a >= 2019-01-05"(这意味着该列a大于等于"2019-01-05",这是一个字符串,而不是 Date 因为的输出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”将成功,因为 Dates(Column a) 可以与 numerics( 17910) 进行比较。


推荐阅读