我有要分组的数据,执行计算然后是最终结果,将其用于下一组中的计算。
我们使用条件语句并按组执行计算,例如:
# Example Data
condition <- c(0,0,0,1,1,1,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0,1,1,0)
col_a <- c(0,0,0,2,3,4,0,0,0,2,4,5,6,0,0,0,0,0,0,0,0,1,2,0)
col_b <- c(0,0,0,10,131,14,0,0,0,22,64,75,96,0,0,0,0,0,0,0,0,41,52,0)
df <- data.frame(condition,col_a,col_b)
这是进行计算的代码,按RunID分组
# Group by RunID
# Perform calculations
# Last value, brought forward to next group
require(dplyr)
output <- df %>%
dplyr::mutate(RunID = data.table::rleid(condition)) %>%
group_by(RunID) %>%
dplyr::mutate(calculation = ifelse(condition == 0,0, ifelse(row_number() == n(),first(col_a) * last(col_b),0))) %>%
dplyr :: mutate(last = tag = ifelse(condition == 0,0,ifelse(row_number()== n(),2,0)))%&gt;%#添加助手ID号。在下面的回答中帮助循环 取消组合()%&gt;% 选择(-RunID) 输出&lt; - data.frame(输出) 头(输出15)
输出:
condition col_a col_b calculation
1 0 0 0 0
2 0 0 0 0
3 0 0 0 0
4 1 2 10 0
5 1 3 131 0
6 1 4 14 28
7 0 0 0 0
8 0 0 0 0
9 0 0 0 0
10 1 2 22 0
11 1 4 64 0
12 1 5 75 0
13 1 6 96 192
14 0 0 0 0
15 0 0 0 0
我想做的是。在第一个结果上,计算列中的结果是28.我想将该值传递给下一个组并插入col_a,第10行(28个替换,2)。然后更新该值。第二组计算结果为96 * 28 = 2688对比(96 * 2 = 192)
结转将始终插入每组的第一行,如上例所示。
预期产出:
condition col_a col_b calculation
1 0 0 0 0
2 0 0 0 0
3 0 0 0 0
4 1 2 10 0
5 1 3 131 0
6 1 4 14 28
7 0 0 0 0
8 0 0 0 0
9 0 0 0 0
10 1 28 22 0
11 1 4 64 0
12 1 5 75 0
13 1 6 96 2688
14 0 0 0 0
15 0 0 0 0
我将子集删除所有0,s。添加了识别到每个组底部的2个数字以进行连续运行,然后使用for循环进行抓取和替换。可能不是最优雅,但似乎有效:
# Subset to remove all 0
subset.no.zero <- subset(output,condition >0)
# Loop to move values
for (i in 1:nrow(subset.no.zero)) {
temp <- ifelse(subset.no.zero$last.tag[i-1] == 2, subset.no.zero$calculation[i-1],subset.no.zero$col_a[i])
subset.no.zero$new_col_a[i] <- data.frame(temp)
}
# Re join by index no.
final_out <- full_join(output,subset.no.zero, by="index")
答案 0 :(得分:4)
我只能提供data.table解决方案,但也许您可以将逻辑转换为dplyr:
library(data.table)
setDT(df)
#first group multiply 2 and 14
df[rleid(condition) %in% 1:2 & condition != 0,
calculation := {
res <- rep(NA_real_, .N)
res[.N] <- col_b[.N] * col_a[1]
res
}
]
#all groups other than first copy col_b
df[, calculation := if (condition[.N] != 0) {
if(is.na(calculation[.N])) {
res <- rep(NA_real_, .N)
res[.N] <- col_b[.N]
res
} else calculation
} else NA_real_,
by = rleid(condition)
]
#cumulative product
df[!is.na(calculation),
calculation := cumprod(calculation)]
#copy values into col_a
df[i = df[, .(condition = condition[1], i = .I[1]),
by = rleid(condition)][condition == 1L][-1, i], #finds rows to replace values
col_a := head(df[!is.na(calculation), calculation], -1)
]
# condition col_a col_b calculation
# 1: 0 0 0 NA
# 2: 0 0 0 NA
# 3: 0 0 0 NA
# 4: 1 2 10 NA
# 5: 1 3 131 NA
# 6: 1 4 14 28
# 7: 0 0 0 NA
# 8: 0 0 0 NA
# 9: 0 0 0 NA
#10: 1 28 22 NA
#11: 1 4 64 NA
#12: 1 5 75 NA
#13: 1 6 96 2688
#14: 0 0 0 NA
#15: 0 0 0 NA
#16: 0 0 0 NA
#17: 0 0 0 NA
#18: 0 0 0 NA
#19: 0 0 0 NA
#20: 0 0 0 NA
#21: 0 0 0 NA
#22: 1 2688 41 NA
#23: 1 2 52 139776
#24: 0 0 0 NA
# condition col_a col_b calculation