You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

dplyr中如何实现Excel引用同列上一行单元格的计算逻辑?

dplyr实现递归自引用列计算方案

问题描述

在可复现R代码示例中,需要使用dplyr包创建名为LowClassSplit的列,该列取值依赖同列紧邻上一行的自身计算结果,逻辑等价于对应Excel示例中黄色高亮列的计算规则:F列每个单元格计算时均引用同列正上方的自身单元格值,蓝色单元格为Excel中通过=FORMULATEXT(...)公式展示的F列计算规则。
待解答问题:

  • dplyr中是否存在实现该自引用列计算的等价方案?
  • 如果dplyr无对应支持,base R中如何实现该需求?

期望输出(与Excel计算结果完全一致)

# A tibble: 10 x 4
   Element SplitCode PreSplitClass ClassAtSplit
   <chr>       <dbl>         <int>        <dbl>
 1 C               0             1            0
 2 B               0             1            0
 3 D               0             1            0
 4 A               0             1            0
 5 A               1             2            2
 6 A               1             3            2
 7 C               0             2            0
 8 B               0             2            0
 9 B               2             3            0
10 B               2             4            0

Excel计算规则示例截图

初始尝试代码

library(dplyr)

data <- 
  data.frame(
    Element = c("C","B","D","A","A","A","C","B","B","B"),
    SplitCode = c(0,0,0,0,1,1,0,0,2,2)  
  )

data <- data %>% group_by(Element) %>% mutate(PreSplitClass=row_number()) %>% ungroup()

data %>%
  mutate(ClassAtSplit =
           case_when(
             SplitCode == 0 ~ as.integer(0), # 无需额外判断值大于0的场景
             SplitCode > lag(SplitCode) ~ PreSplitClass, # 当前值大于上一行值时取当前PreSplitClass
             SplitCode == SplitCode ~ lag(PreSplitClass) # 值相等时取上一行PreSplitClass,已排除0值场景
           )
  )

# 编写LowClassSplit列时遇到自引用问题,以下为未完成的尝试代码
# data %>%
#   mutate(LowClassSplit =
#            case_when(
#              SplitCode == 0 ~ as.integer(0),
#              (SplitCode == lag(SplitCode) && lagitself == 1)|(SplitCode > lag(SplitCode) & PreSplitClass == 1) ~ 1
#            )
#   )

最终实现代码

无需编写复杂递归逻辑,纯dplyr流程即可复现Excel的计算结果,完整代码如下:

library(dplyr)

data <- 
  data.frame(
    Element = c("C","B","D","A","A","A","C","B","B","B"),
    SplitCode = c(0,0,0,0,1,1,0,0,2,2)  
  )

excelCopy <- data %>% 
  group_by(Element) %>% 
  mutate(PreSplitClass = row_number()) %>% 
  ungroup() %>%
  mutate(ClassAtSplit =
           case_when(
             SplitCode == 0 ~ as.integer(0),
             SplitCode > lag(SplitCode) ~ PreSplitClass,
             SplitCode == lag(SplitCode) ~ lag(PreSplitClass)
           )
  ) %>%
  mutate(
    LowClassSplit =
      case_when(
        SplitCode > lag(SplitCode) & SplitCode == 1 ~ PreSplitClass,
        SplitCode == lag(SplitCode) & SplitCode == 1 ~ lag(PreSplitClass),
        TRUE ~ 0L
      )
  )

上述解决方案由Rui Barrada提供。

内容的提问来源于stack exchange,提问作者Curious Jorge - user9788072

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.27 01:57:22