我有一个数据框架,其中包含三个组的日期和相关值,如下所示。
library(lubridate)
library(magrittr)
library(dplyr)
data <-
data.frame(group = rep(c("a", "b", "c"), each = 5),
date = rep(seq(ymd(20200101), ymd(20200105), by = 1),
times = 3),
value = runif(15))
我想执行分组过滤操作,以便按日期提取数据的子集,其中开始日期因组而异。
start_date <- list(a = ymd(20200102), b = ymd(20200104), c = ymd(20200103))
我想用组名索引到开始日期列表中。我尝试按如下操作,但收到一条错误消息。
data %>%
group_by(group) %>%
filter(date >= start_date[[group]])
Error in app$vspace(new_style$`margin-top` %||% 0) :
attempt to apply non-function
我做错了什么
(上述过程的另一种选择是将开始日期设置为数据帧,将数据帧连接到data
,并执行未分组的筛选。这可以按预期工作,但(在我看来(不太优雅,出于其他原因,我更喜欢将开始日期保留为列表。(
start_date_2 <-
data.frame(group = c("a", "b", "c"),
start_date = c(ymd(20200102), ymd(20200104), c = ymd(20200103)))
data %>%
left_join(start_date_2, by = "group") %>%
filter(date >= start_date) %>%
select(-start_date)
我们可以使用cur_group()
访问当前组的名称。这给了我们一个tibble,每个组都是包含当前组名的列,所以我们需要用$group
对其进行子集设置。
library(dplyr)
data %>%
group_by(group) %>%
filter(date >= start_date[[cur_group()$group]])
#> # A tibble: 9 x 3
#> # Groups: group [3]
#> group date value
#> <chr> <date> <dbl>
#> 1 a 2020-01-02 0.225
#> 2 a 2020-01-03 0.345
#> 3 a 2020-01-04 0.110
#> 4 a 2020-01-05 0.0951
#> 5 b 2020-01-04 0.356
#> 6 b 2020-01-05 0.345
#> 7 c 2020-01-03 0.0973
#> 8 c 2020-01-04 0.344
#> 9 c 2020-01-05 0.418
创建于2022-03-29由reprex包(v0.3.0(
我们可以使用purrr
:
library(lubridate)
library(magrittr)
library(dplyr)
library(purrr)
data %>%
group_split(group) %>%
map2(., start_date, ~ filter(.x , date >= .y)) %>%
bind_rows()
#> # A tibble: 9 x 3
#> group date value
#> <fct> <date> <dbl>
#> 1 a 2020-01-02 0.0756
#> 2 a 2020-01-03 0.0535
#> 3 a 2020-01-04 0.338
#> 4 a 2020-01-05 0.332
#> 5 b 2020-01-04 0.992
#> 6 b 2020-01-05 0.356
#> 7 c 2020-01-03 0.751
#> 8 c 2020-01-04 0.949
#> 9 c 2020-01-05 0.778
我们可以使用非等连接
library(data.table)
setDT(data)[data.table(date = do.call(c, start_date),
group = names(start_date)), on = .(group, date >= date)]
group date value
<char> <Date> <num>
1: a 2020-01-02 0.003896343
2: a 2020-01-02 0.052198616
3: a 2020-01-02 0.866560180
4: a 2020-01-02 0.576245169
5: b 2020-01-04 0.531409336
6: b 2020-01-04 0.383936672
7: c 2020-01-03 0.041919498
8: c 2020-01-03 0.363742695
9: c 2020-01-03 0.856596967
另一个选项可能是:
data %>%
filter(date >= start_date[match(group, names(start_date))])
group date value
1 a 2020-01-02 0.29910439
2 a 2020-01-03 0.08603731
3 a 2020-01-04 0.78913465
4 a 2020-01-05 0.40025848
5 b 2020-01-04 0.87568202
6 b 2020-01-05 0.21065155
7 c 2020-01-03 0.47403618
8 c 2020-01-04 0.74996630
9 c 2020-01-05 0.08386366