条件 运行 计数(累计和)在 R (dplyr) 中重置
Conditional running count (cumulative sum) with reset in R (dplyr)
我正在尝试计算一个 运行 计数(即累计和),它以其他变量为条件并且可以针对另一个变量的特定值进行重置。我在 R 中工作,如果可能的话,我更喜欢基于 dplyr
的解决方案。
我想根据以下算法为 运行 计数 cumulative
创建一个变量:
- 计算
id
和 age
组合中的 运行 计数 (cumulative
)
- 每个后续
trial
将 运行 计数 (cumulative
) 增加 1,其中 accuracy = 0
、block = 2
和 condition = 1
- 将每个
trial
的 运行 计数 (cumulative
) 重置为 0,其中 accuracy = 1
、block = 2
和 condition = 1
,以及下一个增量从 1 开始(不是之前的数字)
- 对于
block != 2
或 condition != 1
中的每个 trial
,将 运行 计数 (cumulative
) 保留为 NA
这是一个最小的工作示例:
mydata <- data.frame(id = c(1,1,1,1,1,1,1,1,1,1,1),
age = c(1,1,1,1,1,1,1,1,1,1,2),
block = c(1,1,2,2,2,2,2,2,2,2,2),
trial = c(1,2,1,2,3,4,5,6,7,8,1),
condition = c(1,1,1,1,1,2,1,1,1,1,1),
accuracy = c(0,0,0,0,0,0,0,1,0,0,0)
)
id age block trial condition accuracy
1 1 1 1 1 0
1 1 1 2 1 0
1 1 2 1 1 0
1 1 2 2 1 0
1 1 2 3 1 0
1 1 2 4 2 0
1 1 2 5 1 0
1 1 2 6 1 1
1 1 2 7 1 0
1 1 2 8 1 0
1 2 2 1 1 0
预期输出为:
id age block trial condition accuracy cumulative
1 1 1 1 1 0 NA
1 1 1 2 1 0 NA
1 1 2 1 1 0 1
1 1 2 2 1 0 2
1 1 2 3 1 0 3
1 1 2 4 2 0 NA
1 1 2 5 1 0 4
1 1 2 6 1 1 0
1 1 2 7 1 0 1
1 1 2 8 1 0 2
1 2 2 1 1 0 1
我们可以根据自己的情况使用case_when
来赋值。然后,我们使用 cumsum
添加一个额外的 group_by
条件,以在 temp
列 0 时切换值。在最后的 mutate
步骤中,我们暂时 replace
NA
将 temp
中的值设为 0,然后将 cumsum
置于其上并将 NA
值再次放回原处以获得最终输出。
library(dplyr)
mydata %>%
group_by(id, age) %>%
mutate(temp = case_when(accuracy == 0 & block == 2 & condition == 1 ~ 1,
accuracy == 1 & block == 2 & condition == 1 ~ 0,
TRUE ~ NA_real_)) %>%
ungroup() %>%
group_by(id, age, group = cumsum(replace(temp == 0, is.na(temp), 0))) %>%
mutate(cumulative = replace(cumsum(replace(temp, is.na(temp), 0)),
is.na(temp), NA)) %>%
select(-temp, -group)
# group id age block trial condition accuracy cumulative
# <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
# 1 0 1 1 1 1 1 0 NA
# 2 0 1 1 1 2 1 0 NA
# 3 0 1 1 2 1 1 0 1
# 4 0 1 1 2 2 1 0 2
# 5 0 1 1 2 3 1 0 3
# 6 0 1 1 2 4 2 0 NA
# 7 0 1 1 2 5 1 0 4
# 8 1 1 1 2 6 1 1 0
# 9 1 1 1 2 7 1 0 1
#10 1 1 1 2 8 1 0 2
#11 1 1 2 2 1 1 0 1
这是一个使用 data.table
的选项。根据 match
将 'accuracy'、'block'、'condition' 的 paste
d 值与自定义值的值相结合,按 [=25 分组=]-二进制列的length-id('ind'),'id'和'age',得到'ind'的累加和赋值(:=
)到新列 ('Cumulative')
library(data.table)
setDT(mydata)[, ind := match(do.call(paste0, .SD), c("121", "021")) - 1,
.SDcols = c("accuracy", "block", "condition")
][, Cumulative := cumsum(ind), .(rleid(ind), id, age)
][, ind := NULL][]
# id age block trial condition accuracy Cumulative
# 1: 1 1 1 1 1 0 NA
# 2: 1 1 1 2 1 0 NA
# 3: 1 1 2 1 1 0 1
# 4: 1 1 2 2 1 0 2
# 5: 1 1 2 3 1 0 3
# 6: 1 1 2 4 2 0 NA
# 7: 1 1 2 5 1 1 0
# 8: 1 1 2 6 1 0 1
# 9: 1 1 2 7 1 0 2
#10: 1 2 2 1 1 0 1
我正在尝试计算一个 运行 计数(即累计和),它以其他变量为条件并且可以针对另一个变量的特定值进行重置。我在 R 中工作,如果可能的话,我更喜欢基于 dplyr
的解决方案。
我想根据以下算法为 运行 计数 cumulative
创建一个变量:
- 计算
id
和age
组合中的 运行 计数 ( - 每个后续
trial
将 运行 计数 (cumulative
) 增加 1,其中accuracy = 0
、block = 2
和condition = 1
- 将每个
trial
的 运行 计数 (cumulative
) 重置为 0,其中accuracy = 1
、block = 2
和condition = 1
,以及下一个增量从 1 开始(不是之前的数字) - 对于
block != 2
或condition != 1
中的每个trial
,将 运行 计数 (cumulative
) 保留为NA
cumulative
)
这是一个最小的工作示例:
mydata <- data.frame(id = c(1,1,1,1,1,1,1,1,1,1,1),
age = c(1,1,1,1,1,1,1,1,1,1,2),
block = c(1,1,2,2,2,2,2,2,2,2,2),
trial = c(1,2,1,2,3,4,5,6,7,8,1),
condition = c(1,1,1,1,1,2,1,1,1,1,1),
accuracy = c(0,0,0,0,0,0,0,1,0,0,0)
)
id age block trial condition accuracy
1 1 1 1 1 0
1 1 1 2 1 0
1 1 2 1 1 0
1 1 2 2 1 0
1 1 2 3 1 0
1 1 2 4 2 0
1 1 2 5 1 0
1 1 2 6 1 1
1 1 2 7 1 0
1 1 2 8 1 0
1 2 2 1 1 0
预期输出为:
id age block trial condition accuracy cumulative
1 1 1 1 1 0 NA
1 1 1 2 1 0 NA
1 1 2 1 1 0 1
1 1 2 2 1 0 2
1 1 2 3 1 0 3
1 1 2 4 2 0 NA
1 1 2 5 1 0 4
1 1 2 6 1 1 0
1 1 2 7 1 0 1
1 1 2 8 1 0 2
1 2 2 1 1 0 1
我们可以根据自己的情况使用case_when
来赋值。然后,我们使用 cumsum
添加一个额外的 group_by
条件,以在 temp
列 0 时切换值。在最后的 mutate
步骤中,我们暂时 replace
NA
将 temp
中的值设为 0,然后将 cumsum
置于其上并将 NA
值再次放回原处以获得最终输出。
library(dplyr)
mydata %>%
group_by(id, age) %>%
mutate(temp = case_when(accuracy == 0 & block == 2 & condition == 1 ~ 1,
accuracy == 1 & block == 2 & condition == 1 ~ 0,
TRUE ~ NA_real_)) %>%
ungroup() %>%
group_by(id, age, group = cumsum(replace(temp == 0, is.na(temp), 0))) %>%
mutate(cumulative = replace(cumsum(replace(temp, is.na(temp), 0)),
is.na(temp), NA)) %>%
select(-temp, -group)
# group id age block trial condition accuracy cumulative
# <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
# 1 0 1 1 1 1 1 0 NA
# 2 0 1 1 1 2 1 0 NA
# 3 0 1 1 2 1 1 0 1
# 4 0 1 1 2 2 1 0 2
# 5 0 1 1 2 3 1 0 3
# 6 0 1 1 2 4 2 0 NA
# 7 0 1 1 2 5 1 0 4
# 8 1 1 1 2 6 1 1 0
# 9 1 1 1 2 7 1 0 1
#10 1 1 1 2 8 1 0 2
#11 1 1 2 2 1 1 0 1
这是一个使用 data.table
的选项。根据 match
将 'accuracy'、'block'、'condition' 的 paste
d 值与自定义值的值相结合,按 [=25 分组=]-二进制列的length-id('ind'),'id'和'age',得到'ind'的累加和赋值(:=
)到新列 ('Cumulative')
library(data.table)
setDT(mydata)[, ind := match(do.call(paste0, .SD), c("121", "021")) - 1,
.SDcols = c("accuracy", "block", "condition")
][, Cumulative := cumsum(ind), .(rleid(ind), id, age)
][, ind := NULL][]
# id age block trial condition accuracy Cumulative
# 1: 1 1 1 1 1 0 NA
# 2: 1 1 1 2 1 0 NA
# 3: 1 1 2 1 1 0 1
# 4: 1 1 2 2 1 0 2
# 5: 1 1 2 3 1 0 3
# 6: 1 1 2 4 2 0 NA
# 7: 1 1 2 5 1 1 0
# 8: 1 1 2 6 1 0 1
# 9: 1 1 2 7 1 0 2
#10: 1 2 2 1 1 0 1