group_modify() 下 case_when() 中的 %within% 无效
%within% in case_when() under group_modify() not working
我有以下类型的数据:
library(tidyverse)
library(lubridate)
data <- tibble(a = c(1, 1, 2, 3, 3, 3, 3),
b = c('x', 'y', 'z', 'z', 'z', 'z', 'z'),
c = c('ps', 'ps', 'qs', 'rs', 'rs', 'rs', 'rs'),
d = c(100, 200, 300, 400, 500, 600, 700),
strt = ymd(c('2019-03-20', '2020-01-01', '2018-01-02', '2020-05-01', '2016-01-01', '2020-03-01', '2020-01-01')),
fnsh = ymd(c('3019-03-20', '3020-01-01', '3018-01-02', '2020-06-01', '2016-05-01', '2020-04-01', '2020-06-10')))
我正在使用 group_modify()
基于变量 a、b 和 c(即 data %>% group_by(a, b, c)
)进行分组操作。对于每个组,我需要找到真正开始日期在去年的行。如果 strt 不落在组中任何其他行的 strt 和 fnsh 之间,则它是真实的。我目前的做法是:
test <- data %>%
group_by(a, b, c) %>%
group_modify(function(.x, .y) {
.x %>%
mutate(startLatestYear = case_when(strt > today(tzone = 'CET') - years(1) &
strt <= today(tzone = 'CET') &
!strt %within% (.x %>%
mutate(pushInterval = interval(strt + days(1), fnsh)) %>%
select(pushInterval)) ~ 1,
TRUE ~ 0))}) %>%
ungroup()
这种方法给出:
data <- tibble(a = c(1, 1, 2, 3, 3, 3, 3),
b = c('x', 'y', 'z', 'z', 'z', 'z', 'z'),
c = c('ps', 'ps', 'qs', 'rs', 'rs', 'rs', 'rs'),
d = c(100, 200, 300, 400, 500, 600, 700),
strt = ymd(c('2019-03-20', '2020-01-01', '2018-01-02', '2020-05-01', '2016-01-01', '2020-03-01', '2020-01-01')),
fnsh = ymd(c('3019-03-20', '3020-01-01', '3018-01-02', '2020-06-01', '2016-05-01', '2020-04-01', '2020-06-10')),
startLatestYear = c(0, 1, 0, 1, 0, 1, 1))
需要的是:
data <- tibble(a = c(1, 1, 2, 3, 3, 3, 3),
b = c('x', 'y', 'z', 'z', 'z', 'z', 'z'),
c = c('ps', 'ps', 'qs', 'rs', 'rs', 'rs', 'rs'),
d = c(100, 200, 300, 400, 500, 600, 700),
strt = ymd(c('2019-03-20', '2020-01-01', '2018-01-02', '2020-05-01', '2016-01-01', '2020-03-01', '2020-01-01')),
fnsh = ymd(c('3019-03-20', '3020-01-01', '3018-01-02', '2020-06-01', '2016-05-01', '2020-04-01', '2020-06-10')),
startLatestYear = c(0, 1, 0, 0, 0, 0, 1))
基于 a == 3
、b == 'z'
和 c == 'rs'
的组中有一行(最后一行)应该是组中唯一在 startLatestYear 中为 1 的行。
最后一行是组中唯一在最近一年内具有 strt 并且在组中其他行的间隔之外的行。
目前使用 case_when()
的前两个条件似乎可行。使用 %within%
的第三个条件似乎不起作用。使用 %within%
的条件如何起作用?或者如何实施替代解决方案?
PS:我试过在对 tibble 进行分组之前制作 pushInterval。这样做会为 startLatestYear 生成相同的列,但操作会导致 bind_rows_()
的 'problem' 剥离间隔属性。因此,当前的解决方案可以即时生成 pushInterval。
我认为您不需要使用 group_modify
,这适用于简单的组 mutate
:
data %>%
group_by(a, b, c) %>%
mutate(x = +(purrr::map_lgl(strt, ~ sum(strt <= .x & .x <= fnsh) < 2) &
difftime(Sys.time(), strt, "days") < 365)) %>%
ungroup()
# # A tibble: 7 x 7
# a b c d strt fnsh x
# <dbl> <chr> <chr> <dbl> <date> <date> <int>
# 1 1 x ps 100 2019-03-20 3019-03-20 0
# 2 1 y ps 200 2020-01-01 3020-01-01 1
# 3 2 z qs 300 2018-01-02 3018-01-02 0
# 4 3 z rs 400 2020-05-01 2020-06-01 0
# 5 3 z rs 500 2016-01-01 2016-05-01 0
# 6 3 z rs 600 2020-03-01 2020-04-01 0
# 7 3 z rs 700 2020-01-01 2020-06-10 1
.x
是作为第一个参数传递给 map_lgl
的参数的占位符。在本例中,它也是 strt
,但让我们暂时忘记它。
波浪线函数内部,strt
指的是整个向量,.x
指的是每个单独的 strt
值(长度始终为 1)。 strt <= .x
第一次有效 strt <= strt[1]
。 sum
只计算出现的次数是正确的。 (应该总是 一个 ,因为数字总是在它自己的范围内。)
我有以下类型的数据:
library(tidyverse)
library(lubridate)
data <- tibble(a = c(1, 1, 2, 3, 3, 3, 3),
b = c('x', 'y', 'z', 'z', 'z', 'z', 'z'),
c = c('ps', 'ps', 'qs', 'rs', 'rs', 'rs', 'rs'),
d = c(100, 200, 300, 400, 500, 600, 700),
strt = ymd(c('2019-03-20', '2020-01-01', '2018-01-02', '2020-05-01', '2016-01-01', '2020-03-01', '2020-01-01')),
fnsh = ymd(c('3019-03-20', '3020-01-01', '3018-01-02', '2020-06-01', '2016-05-01', '2020-04-01', '2020-06-10')))
我正在使用 group_modify()
基于变量 a、b 和 c(即 data %>% group_by(a, b, c)
)进行分组操作。对于每个组,我需要找到真正开始日期在去年的行。如果 strt 不落在组中任何其他行的 strt 和 fnsh 之间,则它是真实的。我目前的做法是:
test <- data %>%
group_by(a, b, c) %>%
group_modify(function(.x, .y) {
.x %>%
mutate(startLatestYear = case_when(strt > today(tzone = 'CET') - years(1) &
strt <= today(tzone = 'CET') &
!strt %within% (.x %>%
mutate(pushInterval = interval(strt + days(1), fnsh)) %>%
select(pushInterval)) ~ 1,
TRUE ~ 0))}) %>%
ungroup()
这种方法给出:
data <- tibble(a = c(1, 1, 2, 3, 3, 3, 3),
b = c('x', 'y', 'z', 'z', 'z', 'z', 'z'),
c = c('ps', 'ps', 'qs', 'rs', 'rs', 'rs', 'rs'),
d = c(100, 200, 300, 400, 500, 600, 700),
strt = ymd(c('2019-03-20', '2020-01-01', '2018-01-02', '2020-05-01', '2016-01-01', '2020-03-01', '2020-01-01')),
fnsh = ymd(c('3019-03-20', '3020-01-01', '3018-01-02', '2020-06-01', '2016-05-01', '2020-04-01', '2020-06-10')),
startLatestYear = c(0, 1, 0, 1, 0, 1, 1))
需要的是:
data <- tibble(a = c(1, 1, 2, 3, 3, 3, 3),
b = c('x', 'y', 'z', 'z', 'z', 'z', 'z'),
c = c('ps', 'ps', 'qs', 'rs', 'rs', 'rs', 'rs'),
d = c(100, 200, 300, 400, 500, 600, 700),
strt = ymd(c('2019-03-20', '2020-01-01', '2018-01-02', '2020-05-01', '2016-01-01', '2020-03-01', '2020-01-01')),
fnsh = ymd(c('3019-03-20', '3020-01-01', '3018-01-02', '2020-06-01', '2016-05-01', '2020-04-01', '2020-06-10')),
startLatestYear = c(0, 1, 0, 0, 0, 0, 1))
基于 a == 3
、b == 'z'
和 c == 'rs'
的组中有一行(最后一行)应该是组中唯一在 startLatestYear 中为 1 的行。
最后一行是组中唯一在最近一年内具有 strt 并且在组中其他行的间隔之外的行。
目前使用 case_when()
的前两个条件似乎可行。使用 %within%
的第三个条件似乎不起作用。使用 %within%
的条件如何起作用?或者如何实施替代解决方案?
PS:我试过在对 tibble 进行分组之前制作 pushInterval。这样做会为 startLatestYear 生成相同的列,但操作会导致 bind_rows_()
的 'problem' 剥离间隔属性。因此,当前的解决方案可以即时生成 pushInterval。
我认为您不需要使用 group_modify
,这适用于简单的组 mutate
:
data %>%
group_by(a, b, c) %>%
mutate(x = +(purrr::map_lgl(strt, ~ sum(strt <= .x & .x <= fnsh) < 2) &
difftime(Sys.time(), strt, "days") < 365)) %>%
ungroup()
# # A tibble: 7 x 7
# a b c d strt fnsh x
# <dbl> <chr> <chr> <dbl> <date> <date> <int>
# 1 1 x ps 100 2019-03-20 3019-03-20 0
# 2 1 y ps 200 2020-01-01 3020-01-01 1
# 3 2 z qs 300 2018-01-02 3018-01-02 0
# 4 3 z rs 400 2020-05-01 2020-06-01 0
# 5 3 z rs 500 2016-01-01 2016-05-01 0
# 6 3 z rs 600 2020-03-01 2020-04-01 0
# 7 3 z rs 700 2020-01-01 2020-06-10 1
.x
是作为第一个参数传递给 map_lgl
的参数的占位符。在本例中,它也是 strt
,但让我们暂时忘记它。
波浪线函数内部,strt
指的是整个向量,.x
指的是每个单独的 strt
值(长度始终为 1)。 strt <= .x
第一次有效 strt <= strt[1]
。 sum
只计算出现的次数是正确的。 (应该总是 一个 ,因为数字总是在它自己的范围内。)