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

如何在R语言中基于预定义范围批量计算行求和并生成新列

问题描述

现有如下结构的数据集:

dataset <- structure(
list(
Participant.Id = 1:5,

x1 = c(10L, 20L, 30L, 40L, 50L),
x2 = c(15L, 25L, 35L, 45L, 55L),
x3 = c(20L, 25L, NA, 45L, NA),
x4 = c(25L, 30L, NA, 50L, NA),
x5 = c(NA, 35L, NA, 55L, NA),
x6 = c(NA, 35L, NA, NA, NA),

y1 = c(10L, 20L, 30L, 40L, 50L),
y2 = c(15L, 25L, 35L, 45L, 55L),
y3 = c(20L, 25L, NA, 45L, NA),
y4 = c(25L, 30L, NA, 50L, NA),
y5 = c(NA, 35L, NA, 55L, NA),
y6 = c(NA, 35L, NA, NA, NA),

z1 = c(10L, 20L, 30L, 40L, 50L),
z2 = c(15L, 25L, 35L, 45L, 55L),
z3 = c(20L, 25L, NA, 45L, NA),
z4 = c(25L, 30L, NA, 50L, NA),
z5 = c(NA, 35L, NA, 55L, NA),
z6 = c(NA, 35L, NA, NA, NA),

mt1_oranges_vol = c(100L, 200L, 300L, 400L, 500L),
mt2_oranges_vol = c(110L, 210L, 310L, 410L, 510L),
mt3_oranges_vol = c(120L, 220L, NA, 420L, 520L),
mt4_oranges_vol = c(130L, 230L, NA, 430L, NA),
mt5_oranges_vol = c(NA, 240L, NA, NA, NA),
mt6_oranges_vol = c(NA, NA, NA, NA, NA),
 
mt1_pears_vol = c(101L, 201L, 301L, 401L, 501L),
mt2_pears_vol = c(111L, 211L, 311L, 411L, 511L),
mt3_pears_vol = c(121L, 221L, NA, 421L, 521L),
mt4_pears_vol = c(131L, 231L, NA, 431L, NA),
mt5_pears_vol = c(NA, 241L, NA, NA, NA),
mt6_pears_vol = c(NA, NA, NA, NA, NA),

mt1_apples_vol = c(102L, 202L, 302L, 402L, 502L),
mt2_apples_vol = c(112L, 212L, 312L, 412L, 512L),
mt3_apples_vol = c(122L, 222L, NA, 422L, 522L),
mt4_apples_vol = c(132L, 232L, NA, 432L, NA),
mt5_apples_vol = c(NA, 242L, NA, NA, NA),
mt6_apples_vol = c(NA, NA, NA, NA, NA)),

class = "data.frame", 
row.names = c(NA, -5L)
)

需要为每个mtN_前缀的列生成对应总计列,比如mt1_total_vol是mt1_oranges_vol、mt1_pears_vol、mt1_apples_vol的行求和,以此类推。目前手动写mutate的方式扩展性差,希望通过预定义范围mt_range <- 1:6自动实现。

解决方案

方法1:使用dplyr的across函数(简洁高效)

利用across批量处理前缀,自动生成总计列:

library(dplyr)
library(stringr)

mt_range <- 1:6

dataset <- dataset %>%
  mutate(
    across(
      # 匹配所有mtN_开头的列模式
      matches(paste0("mt", mt_range, "_", collapse = "|")),
      # 提取当前列的mtN_前缀,计算对应列的行和
      ~ rowSums(select(., starts_with(str_extract(cur_column(), "^mt\\d+_"))), na.rm = FALSE),
      # 重命名新列为mtN_total_vol格式
      .names = "{str_replace(.col, '_.*', '_total_vol')}"
    )
  )

方法2:使用purrr函数式编程

通过map_dfc批量生成总计列后绑定到原数据:

library(dplyr)
library(purrr)

mt_range <- 1:6

# 批量生成各mtN的总计列
total_cols <- map_dfc(mt_range, function(n) {
  prefix <- paste0("mt", n, "_")
  dataset %>%
    select(starts_with(prefix)) %>%
    rowSums(na.rm = FALSE) %>%
    as.data.frame() %>%
    rename(!!paste0("mt", n, "_total_vol") := .)
})

# 合并总计列到原数据集
dataset <- bind_cols(dataset, total_cols)

方法3:Base R循环(直观易懂)

用基础循环遍历每个mt编号,生成对应总计列:

mt_range <- 1:6

for(n in mt_range) {
  prefix <- paste0("mt", n, "_")
  total_col_name <- paste0("mt", n, "_total_vol")
  # 筛选当前前缀的列并计算行和
  dataset[[total_col_name]] <- rowSums(dataset[, startsWith(names(dataset), prefix)], na.rm = FALSE)
}

以上三种方法都能实现自动生成总计列的需求,后续新增mt7_等列时,只需调整mt_range的范围即可,无需修改核心逻辑。

内容的提问来源于stack exchange,提问作者y.a

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.02 18:10:04