如何用双花括号过滤日期?

How to filter dates with double curly brackets?

与我关于 ggplot 中的双大括号的其他 类似,我也在努力使用双大括号来过滤日期。在此功能中,用户可以指定一个时间段(周、月),然后该功能会根据相应的时间段进行过滤。例如,选择 'month' 应该会导致函数只关注 MonthMonth_score 列。但是,它一直失败并提供不正确的输出:

这是我的示例数据以及我所做的 2 次尝试:

#Sample data

library(dplyr)
library(lubdridate)

test <- tibble(Week = seq(as.Date("2014-09-04"), by = "week", length.out = 8),
               Month = ymd(rep('2014-09-01', 4), rep('2014-10-01', 4)),
               Week_score = c(2, 3, 4, 6, 5, 7, 8, 9),
               Month_score = c(15, NA, NA, NA, 29, NA, NA, NA))

尝试 1--没有删除任何列(这是不正确的):

date_filter <- function(data, time_period = c("Week", "Month"), start_date = NA_Date_) {


  data %>%
    filter({{time_period}} > start_date)
}

date_filter(data = test, time_period = "Week", start_date = '2014-09-06')

尝试 2:我明确指出 start_date 是一个日期,但我收到以下错误

date_filter <- function(data, time_period = c("Week", "Month"), start_date = NA_Date_) {


  data %>%
    filter({{time_period}} > as.Date(start_date))
}

date_filter(data = test, time_period = "Week", start_date = '2014-09-06')

{{}} 用于不带引号的变量名,而不是字符串。

在调用你的函数时从 time_period 中删除 "",并且它有效:

date_filter <- function(data, time_period, start_date = NA_Date_) {
  
  
  data %>%
    filter({{time_period}} > as.Date(start_date))
}

date_filter(data = test, time_period = Week, start_date = '2014-09-06')

#> # A tibble: 7 × 4
#>   Week       Month      Week_score Month_score
#>   <date>     <date>          <dbl>       <dbl>
#> 1 2014-09-11 2014-09-01          3          NA
#> 2 2014-09-18 2014-09-01          4          NA
#> 3 2014-09-25 2014-09-01          6          NA
#> 4 2014-10-02 2014-10-01          5          29
#> 5 2014-10-09 2014-10-01          7          NA
#> 6 2014-10-16 2014-10-01          8          NA
#> 7 2014-10-23 2014-10-01          9          NA

reprex package (v2.0.1)

于 2022-04-02 创建

rlang 有一个很好的 article,我建议大家在使用 {{}} 之前阅读它。

为什么 time_period = "Week" 在第一个函数中起作用而在另一个函数中不起作用?

因为 {{time_period}} 被解释为字符串,而不是变量 Week。您实际上是在尝试比较第一个函数中的 "Week" > "2014-09-06"(始终为 TRUE)和第二个函数中的 "Week" > as.Date("2014-09-06")(这使得 R 想要将 "Week" 转换为一个日期,因此你会得到一个错误。

如果我们想传递带引号或不带引号的参数,则使用 ensym

转换为 sym
date_filter <- function(data, time_period = c("Week", "Month"), 
      start_date = NA_Date_) {

  time_period <- rlang::ensym(time_period)
  data %>%
    filter(!!time_period > start_date)
}

-测试

> date_filter(data = test, time_period = "Week", start_date = '2014-09-06')
# A tibble: 7 × 4
  Week       Month      Week_score Month_score
  <date>     <date>          <dbl>       <dbl>
1 2014-09-11 2014-09-01          3          NA
2 2014-09-18 2014-09-01          4          NA
3 2014-09-25 2014-09-01          6          NA
4 2014-10-02 2014-10-01          5          29
5 2014-10-09 2014-10-01          7          NA
6 2014-10-16 2014-10-01          8          NA
7 2014-10-23 2014-10-01          9          NA
> 
> date_filter(data = test, time_period = Week, start_date = '2014-09-06')
# A tibble: 7 × 4
  Week       Month      Week_score Month_score
  <date>     <date>          <dbl>       <dbl>
1 2014-09-11 2014-09-01          3          NA
2 2014-09-18 2014-09-01          4          NA
3 2014-09-25 2014-09-01          6          NA
4 2014-10-02 2014-10-01          5          29
5 2014-10-09 2014-10-01          7          NA
6 2014-10-16 2014-10-01          8          NA
7 2014-10-23 2014-10-01          9          NA