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

如何在R语言中借助tidyverse基于年份对列进行条件求和?

使用tidyverse实现按年份条件求和生成累计列

问题背景

现有如下R数据框:

df <- data.frame(
  id = c(100023, 100024, 100034, 100064, 100054, 100032),
  year = c(1995, 1996, 1997, 1998, 1999, 2000),
  n_1995_point_count = c(10, 5, 3, 8, 2, 1),
  n_1996_point_count = c(7, 6, 2, 4, 3, 1),
  n_1997_point_count = c(3, 5, 1, 2, 6, 0),
  n_1998_point_count = c(8, 4, 9, 2, 1, 0),
  n_1999_point_count = c(3, 4, 9, 2, 2, 0),
  n_2000_point_count = c(5, 2, 3, 1, 4, 0)
)

需要新增一列cumulative_sum,规则为:对每行,求和所有年份小于当前行year值的n_XXXX_point_count列(1995年无前置年份,累计和为0),最终输出如下:

id year n_1995_point_count n_1996_point_count n_1997_point_count n_1998_point_count n_1999_point_count n_2000_point_count cumulative_sum
1 100023 1995                 10                  7                  3                  8                  3                  5              0
2 100024 1996                  5                  6                  5                  4                  4                  2              5
3 100034 1997                  3                  2                  1                  9                  9                  3              5
4 100064 1998                  8                  4                  2                  2                  2                  1             14
5 100054 1999                  2                  3                  6                  1                  2                  4             12
6 100032 2000                  1                  1                  0                  0                  0                  0              2

解决方案(tidyverse语法)

方法一:行处理直接求和

通过行分组+列匹配的方式,直接逐行筛选符合条件的列并求和:

library(tidyverse)

df_result <- df %>%
  rowwise() %>%
  mutate(
    cumulative_sum = sum(
      c_across(starts_with("n_")),
      .names_to = "col_year",
      .name_spec = ~ str_extract(., "\\d{4}") %>% as.integer(),
      .fns = ~ .x < year
    )
  ) %>%
  ungroup()

print(df_result)

代码说明

  • rowwise():将数据框按行分组,确保后续操作逐行执行
  • c_across(starts_with("n_")):选中所有年份对应的点数列
  • .name_spec:用正则表达式从列名中提取4位年份数字并转为整数
  • .fns = ~ .x < year:筛选出年份小于当前行year的列,仅对这些列求和
  • ungroup():取消行分组,恢复数据框常规结构

方法二:长格式转换后计算

先将宽格式转为长格式,计算累计和后再转回宽格式,逻辑更直观:

df_result2 <- df %>%
  pivot_longer(
    cols = starts_with("n_"),
    names_to = "year_col",
    values_to = "points"
  ) %>%
  mutate(year_col = str_extract(year_col, "\\d{4}") %>% as.integer()) %>%
  group_by(id) %>%
  mutate(cumulative_sum = sum(ifelse(year_col < year, points, 0))) %>%
  pivot_wider(
    names_from = year_col,
    names_prefix = "n_",
    names_suffix = "_point_count",
    values_from = points
  ) %>%
  ungroup() %>%
  select(names(df), cumulative_sum)

print(df_result2)

代码说明

  • pivot_longer:将宽格式的年份列转为长格式,每行对应一个id、年份和点数
  • 提取列名中的年份数值后,按id分组
  • 对每个id下的行,判断年份是否符合条件,求和得到累计值
  • pivot_wider:转回宽格式并恢复原始列顺序

内容的提问来源于stack exchange,提问作者llamatrauma

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.15 19:17:35