在R中用case_when结合lag函数实现累积操作,是否需要循环?
解决累积字符串操作的报错问题
你遇到的报错是因为mutate是整列批量计算的,在计算id2的过程中,lag(id2)无法引用到还未完全创建的id2列的上一行值。要实现这种依赖上一次结果的累积操作,应该用purrr包的accumulate2函数,它能逐行迭代计算,每一步都用上一次的输出作为下一次的输入。
解决方案代码
library(tidyverse) df <- tibble(code = c("start","fi","fu","fi","start","fi","start","fu"), id = c("x,y,", "y,", "z,p,", "p,", "z,p,", "p,", "x,y,z,", "p,q,")) df %>% mutate( id2 = accumulate2(code, id, ~ { case_when( ..2 == "start" ~ ..3, ..2 == "fu" ~ paste0(..1, ..3), ..2 == "fi" ~ str_replace_all(..1, ..3, "") ) }, .init = "") %>% tail(-1) )
代码说明
accumulate2(code, id, ...):同时迭代code和id两个向量,..1代表上一次计算得到的id2值,..2是当前行的code,..3是当前行的id。.init = "":设置初始值为空字符串,确保第一行计算时有合法的上一次结果。tail(-1):去掉accumulate2返回结果中的初始空字符串,让id2的长度和原数据一致。case_when逻辑完全匹配你的需求:- 当
code为start时,将当前id作为新的起点; - 当
code为fu时,把当前id拼接到上一次的结果后; - 当
code为fi时,从上一次的结果中移除当前id对应的字符串。
- 当
运行结果
# A tibble: 8 × 3 code id id2 <chr> <chr> <chr> 1 start x,y, x,y, 2 fi y, x, 3 fu z,p, x,z,p, 4 fi p, x,z, 5 start z,p, z,p, 6 fi p, z, 7 start x,y,z, x,y,z, 8 fu p,q, x,y,z,p,q,
注:你的期望输出第七行id2为x,z,,这和你描述的start重置逻辑不符,上述代码严格遵循你提出的规则执行。如果需要调整逻辑,可以修改case_when中的对应分支。
内容的提问来源于stack exchange,提问作者Edoardo
相关产品推荐
相关产品推荐

