R语言单行DataFrame按相近列名分组计算均值的实现问题
R按列名前缀分组计算均值实现方案
核心思路
你的列名遵循「公共前缀+末尾数字」的命名规则,无需使用模糊匹配,直接提取列名的非数字后缀作为分组依据即可实现精准分组,完全规避agrep的误匹配问题,同时自动适配每组不定数量的列。
可运行实现代码
方案1:Base R 原生实现(无需安装第三方包)
# 读入测试数据 df <- structure(list(poms_tat1 = 0.370882118644872, poms_tat2 = 0.491592168116328, poms_tat3 = 0.395819547420188, tens1 = -0.113960576459638, tens2 = -0.146254484825426, tens3 = -0.44114940169153, bat_ratio1 = 1, isi1 = 0.0944068640061701, isi2 = 0.597785124823513, isi3 = 0.676617801589949, isi4 = 0.143940321201716, sleepqual = 0.378902118888194, se1 = 0.393610946830482, se2 = 0.0991899501072693, se3 = 0.501745206004254, challenge1 = 0.417855447018672, challenge2 = 0.393610946830482, challenge3 = 0.417855447018672, threat1 = -0.13014390184863, threat2 = -0.34027852368936, threat3 = -0.269679944985297, reat1 = 0.565825152115738, reat2 = 0.571605347479646, reat3 = 0.497468338163091, reat4 = 0.484881137876427, reat5 = 0.494727444918154, selfman1 = 0.389249472080761, selfman2 = 0.40609787800914, selfman3 = 0.418121005003545, selfman4 = 0.467099366496914, selfman5 = 0.205356548067582, selfman6 = 0.464385939554693, selfman7 = 0.379071252751718, eli1 = 0.250872603002127, eli2 = 0, eli3 = 0.265908011739155), row.names = 1L, class = "data.frame") # 提取列名分组:去掉末尾所有数字得到公共前缀 col_groups <- sub("\\d+$", "", names(df)) # 按分组拆分列并计算每组均值 result <- as.data.frame(sapply(split.default(df, col_groups), function(x) rowMeans(x, na.rm = TRUE)))
运行后result的输出完全符合预期,例如poms_tat列均值为0.4194313,tens列均值为-0.2337882,无数字后缀的sleepqual列会保留原值。
方案2:tidyverse 风格实现(可读性更高)
library(tidyverse) result <- df %>% # 宽表转长表 pivot_longer(everything(), names_to = "col_name") %>% # 提取分组前缀 mutate(group = str_remove(col_name, "\\d+$")) %>% # 分组求均值 group_by(group) %>% summarise(mean_val = mean(value, na.rm = TRUE)) %>% # 转回宽表 pivot_wider(names_from = group, values_from = mean_val)
方案优势
- 分组精准:基于列名规则硬匹配,不会出现
threat和reat误归为一类的问题 - 适配性强:自动支持每组任意数量的列,无论1列、3列还是7列都能正确计算
- 代码简洁:无需嵌套循环,维护成本低
内容的提问来源于stack exchange,提问作者Leo
相关产品推荐
相关产品推荐

