R语言实现动态自引用的tenure列生成(无for循环)
在R的data.frame中生成按条件递增的ten列(无for循环实现)
需求:给data.frame新增ten列,初始值为1;若当前行的occ与前一行的occPrev相等,ten递增1;若不相等则重置为1。要求避免使用for循环,同时支持按id分组的通用场景。
示例数据
df <- data.frame( id = c(1,1,1,2,2,2), occ = c("A", "A", "B", "C", "C", "C"), occPrev = c("A", "A", "A", "C", "D", "C") )
期望输出
expected_df <- data.frame( id = c(1,1,1,2,2,2), occ = c("A", "A", "B", "C", "C", "C"), occPrev = c("A", "A", "A", "C", "D", "C"), ten = c(1,2,1,1,1,1) )
解决方案(dplyr + rle)
利用rle(游程编码)处理连续重复的逻辑,结合dplyr的分组功能,完美实现无循环需求:
library(dplyr) df_result <- df %>% group_by(id) %>% mutate( # 标记当前行与前一行的occ/occPrev是否相等 is_same = occ == occPrev, # 对连续相等的标记生成递增序号 seq_id = inverse.rle(within.list(rle(is_same), values <- seq_along(values))), # 根据标记生成ten列:相等时用递增序号,否则重置为1 ten = ifelse(is_same, seq_id, 1) ) %>% ungroup() %>% select(-is_same, -seq_id) # 清理中间变量
简化版(省略中间变量)
如果不需要保留中间标记列,可以直接整合逻辑:
df_result <- df %>% group_by(id) %>% mutate( ten = ifelse(occ == occPrev, inverse.rle(within.list(rle(occ == occPrev), values <- seq_along(values))), 1) ) %>% ungroup()
运行后df_result的ten列将完全匹配期望输出,且支持任意多分组场景,效率远高于for循环。
内容的提问来源于stack exchange,提问作者ykkoca
相关产品推荐
相关产品推荐

