【发布时间】:2021-03-13 13:21:19
【问题描述】:
我正在寻找一个整洁的解决方案,最好使用tidyverse
这个问题与this answer 一致,但它确实有一个额外的转折。我的数据有一个整体分组变量“grp”。在每个这样的组中,我想根据“试用”定义的子组中的累积总和(cumsum)执行计算,这里是X和@987654325 @。
但是,对于两个子组(试验“X”和试验“Y”)内的计算,我需要使用单一的、共同的组特定基线,即试验是 B。
我想要的结果是Value3在下面的数据集中desired_outcome:
# library(tidyverse)
# library(dplyr)
desired_outcome # see below I got this `desired_outcome`
# A tibble: 10 x 6
# Groups: grp [2]
grp trial yr value1 value2 Value3
<chr> <fct> <dbl> <dbl> <dbl> <dbl>
1 A B 2021 2 0 2
2 A X 2022 3 1 5
3 A X 2023 4 2 10
4 A Y 2022 5 3 7
5 A Y 2023 6 4 16
6 B B 2021 0 2 0
7 B X 2022 1 3 3
8 B X 2023 2 4 8
9 B Y 2022 3 5 5
10 B Y 2023 4 6 14
我的最小工作示例。数据优先,
tabl <- tribble(~grp, ~trial, ~yr, ~value1, ~value2,
'A', "B", 2021, 2, 0,
'A', "X", 2022, 3, 1,
'A', "X", 2023, 4, 2,
'A', "Y", 2022, 5, 3,
'A', "Y", 2023, 6, 4,
'B', "B", 2021, 0, 2,
'B', "X", 2022, 1, 3,
'B', "X", 2023, 2, 4,
'B', "Y", 2022, 3, 5,
'B', "Y", 2023, 4, 6) %>%
mutate(trial = factor(trial, levels = c("B", "X", "Y"))) %>%
arrange(grp, trial, yr)
现在,我需要使用 group_by(),但我无法在 trial 上进行分组,因为我需要在计算“X”和“Y”时使用基线 B。
undesired_outcome_tidier_code <- tabl %>%
group_by(grp) %>% # this do not work!
mutate(Value1.1 = cumsum(value1),
Value2.1 = lag(cumsum(value2), default = 0),
Value3 = Value1.1 + Value2.1) %>%
select(-Value1.1, -Value2.1)
在undesired_outcome_tidier_code 中,第 4-5 行和第 9-10 行显然没有使用第 1 行和第 6 行作为基线。如图所示,
undesired_outcome_tidier_code
# A tibble: 10 x 6
# Groups: grp [2]
grp trial yr value1 value2 Value3
<chr> <fct> <dbl> <dbl> <dbl> <dbl>
1 A B 2021 2 0 2
2 A X 2022 3 1 5
3 A X 2023 4 2 10
4 A Y 2022 5 3 17
5 A Y 2023 6 4 26
6 B B 2021 0 2 0
7 B X 2022 1 3 3
8 B X 2023 2 4 8
9 B Y 2022 3 5 15
10 B Y 2023 4 6 24
我正在寻找一个解决方案,让我以整洁的方式获得desired_outcome(见下文)。
在这个较小的示例中,我可以绕过它,找到我的desired_outcome,但这是一个麻烦两步解决方案。一定有更好/更整洁的方式。
step1 <- tabl %>% arrange(grp, trial, yr) %>% filter(trial != 'Y') %>%
group_by(grp) %>%
mutate(Value1.1 = cumsum(value1),
Value2.1 = lag(cumsum(value2), default = 0),
Value3 = Value1.1 + Value2.1)
step2 <- tabl %>% arrange(grp, trial, yr) %>% filter(trial != 'X') %>%
group_by(grp) %>%
mutate(Value1.1 = cumsum(value1),
Value2.1 = lag(cumsum(value2), default = 0),
Value3 = Value1.1 + Value2.1)
desired_outcome <- rbind(step1,
step2 %>% filter(trial != 'B')
) %>% select(-Value1.1, -Value2.1) %>% arrange(grp, trial, yr)
【问题讨论】:
-
我尝试了一个更明确的标题并扩展了解释。我希望你不介意:) 干杯
标签: tidyverse r optimization tidyverse cumsum