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

按Y1/Y2/Y3列名分组实现跨行累加(跳过零值+Y1处重置)的函数修正需求

Y1/Y2/Y3列名分组实现跨行累加(跳过零值+Y1处重置)的函数修正需求

核心需求回顾

先明确你要实现的规则,避免理解偏差:

  • 按列名后缀分组:每一组由Y1.xxx、Y2.xxx、Y3.xxx组成(比如Y1.Base/Y2.Base/Y3.Base是一组,Y1.Scenario_1/Y2.Scenario_1/Y3.Scenario_1是另一组)
  • 每组内按Y1→Y2→Y3的顺序做带零值跳过的累加:
    • 零值单元格保持原样,不参与累加计算,也不被累加结果覆盖
    • 非零单元格的累加值 = 前面所有非零的同组单元格的和 + 当前单元格的值
  • 每组从Y1开始重置累加器,跨组不继承累加值

原函数的问题分析

你的原函数有两个关键逻辑错误:

  1. 重置累加器的时机错误:原函数是在处理完Y1列后才重置累加器,导致Y2/Y3的累加器初始为0,无法继承Y1的非零值
  2. 跨组累加未隔离:原函数是全局遍历整行的所有列,只有遇到Y1列才重置,但重置是在处理完Y1值之后,导致Y1值会加上上一组最后残留的累加值(比如3C行的Y1.Scenario_3被上一组Y3.Scenario_1的-1污染,变成1 + (-1) = 0)

修正方案:按分组处理(推荐用dplyr+purrr,更清晰)

我推荐先把列按后缀分组,然后对每组单独处理累加逻辑,这样能彻底避免跨组污染,逻辑也更直观:

library(dplyr)
library(purrr)

# 定义单组的累加函数:输入一组的Y1/Y2/Y3值,返回处理后的结果
group_cumsum <- function(group_vals) {
  cum_sum <- 0
  result <- numeric(3)
  for (i in 1:3) {
    val <- group_vals[i]
    if (val != 0) {
      cum_sum <- cum_sum + val
      result[i] <- cum_sum
    } else {
      result[i] <- 0  # 保持原零值
    }
  }
  result
}

# 处理数据:
df_processed <- df %>%
  # 保留第一列作为标识,其他列按后缀分组
  mutate(across(-Ratingstufe, .names = "{.col}")) %>%
  # 把列按后缀拆分:提取Y1/Y2/Y3后面的部分作为分组键
  pivot_longer(-Ratingstufe, names_to = c("Y", "group"), names_sep = "\\.") %>%
  pivot_wider(names_from = Y, values_from = value) %>%
  # 对每个分组应用累加函数
  mutate(across(Y1:Y3, ~ group_cumsum(c(Y1, Y2, Y3))[which(c(Y1, Y2, Y3) == .x)], .by = group)) %>%
  # 转回原宽格式
  pivot_longer(Y1:Y3, names_to = "Y", values_to = "value") %>%
  unite(col = "col_name", Y, group, sep = ".") %>%
  pivot_wider(names_from = col_name, values_from = value) %>%
  # 恢复原列顺序(可选,和输入列顺序一致)
  select(all_of(names(df)))

# 查看结果(重点看3C行)
tail(df_processed)

或者修正原循环函数(保持基础R风格)

如果你更倾向于用基础R的循环,需要调整重置时机和分组逻辑:

cumsum_ignore_zeros_fixed <- function(row, col_names) {
  # 先把列按分组拆分,获取每个分组的列索引
  groups <- unique(sub("Y[1-3]\\.", "", col_names))
  result <- numeric(length(row))
  
  for (g in groups) {
    # 获取当前组的三个列索引:Y1.xxx, Y2.xxx, Y3.xxx
    group_cols <- grep(paste0("Y[1-3]\\.", g), col_names)
    if (length(group_cols) != 3) next  # 跳过不完整的组
    
    cum_sum <- 0
    for (i in group_cols) {
      val <- row[i]
      if (val != 0) {
        cum_sum <- cum_sum + val
        result[i] <- cum_sum
      } else {
        result[i] <- val
      }
    }
  }
  return(result)
}

# 应用修正后的函数
df_fixed <- df
df_fixed[-1] <- t(apply(df_fixed[-1], 1, cumsum_ignore_zeros_fixed, col_names = names(df_fixed)[-1]))

# 查看结果
tail(df_fixed)

验证结果

运行以上任意代码后,3C行的结果会符合你的预期:

  • Y3.Scenario_1:2(Y1) + (-1)(Y3)= 1
  • Y1.Scenario_3:保持1(没有跨组累加)
  • Y2.Scenario_3:1(Y1) + 2(Y2)= 3
  • Y3.Scenario_3:3 + 1 = 4

完全匹配你标记的期望结果。

备注:内容来源于stack exchange,提问作者Ingrid

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.20 07:53:15