r - 对子组内的计算(cumsum)使用单一、通用的组特定基线
问题描述
我正在寻找一个整洁的解决方案,最好使用tidyverse
这个问题与这个答案是一致的,但是它确实有一个额外的转折。我的数据有一个整体分组变量“grp”。在每个这样的组中,我想根据“试验”定义的子组cumsum
中的累积总和( )执行计算,这里和。X
Y
但是,对于两个子组(试验“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
因为我需要使用基线B
来计算“X”和“Y”。
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
(见下文)整洁的解决方案。
在这个较小的示例中,我可以绕过它来获得 my 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)
解决方案
加上purrr
,您可以执行以下操作:
map(.x = c("X", "Y"),
~ tabl %>%
arrange(grp, trial, yr) %>%
filter(trial != .x) %>%
group_by(grp) %>%
mutate(value3 = cumsum(value1) + lag(cumsum(value2), default = 0))) %>%
reduce(full_join) %>%
arrange(grp, trial, yr)
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
推荐阅读
- c++ - C++11 特性 std::map::at 在旧版本的 C++ 上编译
- c# - 如何将 IEnumerable 与 Process.Start 的输出事件处理程序一起使用?
- java - FirebaseListAdapter 无法应用
- asp.net-core - 如何将默认参数传递给 ASP .Net Core 控制器?
- ruby-on-rails - Ruby on Rails ActiveRecord。如何防止在构建方法之后从数据库中获取集合?
- python - 在 Anaconda 的 Spyder4 Python 中运行脚本在控制台中看不到已导入的模块
- python - 当我尝试在 PyGame 中制作游戏时,窗口不会出现
- python-3.x - 将操作应用于 pandas 中的组
- swift - 如何使用 Firestore 获取请求获取特定字段数据?
- reactjs - 反应酶包装器实例返回 Null 或 undefined