如何用dplyr引用同一列上一行计算值生成nameCntSpltGrp列?
修复dplyr中依赖上一行计算值的列生成问题
问题说明
需要在dplyr中生成nameCntSpltGrp列,计算逻辑如下:
- 若当前行
nameCntSplt> 0,取值为nameCntSplt - 若当前行
Name与上一行Name相同,取值为上一行的nameCntSpltGrp - 其余情况取值为0
原代码中使用lag()无法实现需求,因为mutate里的lag()引用的是列的原始值,而非逐行计算后的实时结果。
解决方案
使用purrr::accumulate()函数逐行计算,该函数可以将上一次的计算结果传递到下一行,完美适配依赖上一行结果的场景。
完整代码
library(dplyr) library(purrr) myData <- data.frame( Name = c("R","R","T","R","N","N"), Group = c(0,0,0,0,1,1) ) myDataFill <- myData %>% group_by(Name, Group) %>% mutate(nameCnt = row_number()) %>% mutate(subGrpRank = ifelse(Group > 0, row_number(), 0)) %>% mutate(nameCntSplt = ifelse(subGrpRank == 1, nameCnt, 0)) %>% ungroup() %>% mutate(nameCntSpltGrp = accumulate( .x = 1:n(), .f = function(prev_val, i) { if (nameCntSplt[i] > 0) { nameCntSplt[i] } else if (Name[i] == Name[i-1]) { prev_val } else { 0 } }, .init = 0 )[-1]) # 去掉初始值,匹配数据行数 print.data.frame(myDataFill)
代码解释
accumulate()的.x参数传入行号序列1:n(),用于逐行索引数据.f定义计算逻辑:- 当当前行
nameCntSplt大于0时,直接取该值 - 否则判断当前行
Name是否与上一行一致,一致则用上一次的计算结果prev_val - 其余情况返回0
- 当当前行
.init = 0设置初始值(对应第0行的虚拟值),最后用[-1]去掉这个初始值,保证结果与原数据行数匹配
运行结果
Name Group nameCnt subGrpRank nameCntSplt nameCntSpltGrp 1 R 0 1 0 0 0 2 R 0 2 0 0 0 3 T 0 1 0 0 0 4 R 0 3 0 0 0 5 N 1 1 1 1 1 6 N 1 2 2 0 1
内容的提问来源于stack exchange,提问作者Village.Idyot
相关产品推荐
相关产品推荐

