如何按列名模式分组高效实现逐行累积均值计算?
高效按列组计算逐行累积均值
背景
需要按列名前缀(如示例中的a、b)划分列组,逐行计算每组内从首列开始的累积均值:
- 对以
a开头的列:a1_2是a1和a2的均值,a1_3是a1、a2、a3的均值,a1_4是a1至a4的均值; - 对以
b开头的列,遵循相同规则生成b1_2、b1_3、b1_4。
示例数据:
a1 = c(1, 2, 3) a2 = c(4, 5, 6) a3 = c(7, 8, 9) a4 = c(10, 11, 12) b1 = c(10, 20, 30) b2 = c(40, 50, 60) b3 = c(70, 80, 90) b4 = c(100, 110, 120) df = data.frame(a1, a2, a3, a4, b1, b2, b3, b4)
手动逐个定义新变量的方法效率极低,需要更高效的批量处理方案。
问题
如何批量生成这类有规律的累积均值列,避免手动逐个编写计算逻辑?
解决方案
方法1:dplyr + purrr 实现
利用dplyr的数据操作能力结合purrr的迭代功能,批量处理每个列组:
library(dplyr) library(purrr) # 提取所有列组的前缀 prefixes <- unique(substr(names(df), 1, 1)) # 定义生成单组累积均值的函数 add_cumulative_means <- function(data, prefix) { # 获取当前前缀对应的所有列 target_cols <- names(data)[startsWith(names(data), prefix)] # 遍历需要计算的累积长度(从2到列组总列数) cumulative_cols <- map(2:length(target_cols), function(k) { # 计算每行的累积均值并命名 rowMeans(data[, target_cols[1:k], drop = FALSE]) %>% setNames(paste0(prefix, "1_", k)) }) %>% bind_cols() # 将新列与原数据合并 bind_cols(data, cumulative_cols) } # 对所有前缀应用函数,生成最终结果 result <- reduce(prefixes, add_cumulative_means, .init = df) print(result)
方法2:data.table 高效实现(适合大数据)
data.table的语法更简洁,处理大数据集时效率更高:
library(data.table) setDT(df) # 提取列组前缀 prefixes <- unique(substr(names(df), 1, 1)) # 遍历每个前缀批量生成新列 for (prefix in prefixes) { target_cols <- grep(paste0("^", prefix), names(df), value = TRUE) for (k in 2:length(target_cols)) { new_col_name <- paste0(prefix, "1_", k) df[, (new_col_name) := rowMeans(.SD[, target_cols[1:k], with = FALSE])] } } print(df)
方法3:Base R 原生实现
无需额外加载包,用原生代码完成批量处理:
# 提取列组前缀 prefixes <- unique(substr(names(df), 1, 1)) # 遍历每个前缀生成累积均值列 for (prefix in prefixes) { target_cols <- grep(paste0("^", prefix), names(df), value = TRUE) n_cols <- length(target_cols) for (k in 2:n_cols) { new_col_name <- paste0(prefix, "1_", k) df[[new_col_name]] <- rowMeans(df[, target_cols[1:k], drop = FALSE]) } } print(df)
三种方法最终都会生成符合要求的累积均值列,输出结果一致:
a1 a2 a3 a4 b1 b2 b3 b4 a1_2 a1_3 a1_4 b1_2 b1_3 b1_4 1 1 4 7 10 10 40 70 100 2.5 4 5.5 25 40 55 2 2 5 8 11 20 50 80 110 3.5 5 6.5 35 50 65 3 3 6 9 12 30 60 90 120 4.5 6 7.5 45 60 75
内容的提问来源于stack exchange,提问作者zhiwei li
相关产品推荐
相关产品推荐

