如何在大数据集中用循环结合rowMeans函数批量计算新变量
高效计算多疾病题项行均值的解决方案
问题背景
我有一份宽格式疾病数据集,包含54种疾病,每种疾病对应18个题项,变量命名规则为epi_scm.1至epi_scm.18、ms_scm.1至ms_scm.18这类(前缀是疾病名称,后缀是题项序号)。需要为每种疾病计算其18个题项的行均值,但手动逐个处理效率太低,希望找到高效的实现方式。
我之前尝试过逐个子集化数据的方法,但耗时太长,不适合主分析:
#Subset data to include only 42 columns subset_epi <- df4[, 1:42] # Replace 1:42 with the indices or column names of the columns I want to keep subset_epi <- subset_epi[complete.cases(subset_epi), ] #Organize index numbers subset rownames(subset_epi) <- 1:nrow(subset_epi) dim(subset_epi) #New variable Morality = Mean Score for Morality subset_epi$Morality <- rowMeans(na.omit(subset_epi[, c("epi_scm_1", "epi_scm_2", "epi_scm_3", "epi_scm_4", "epi_scm_5")]))
方法1:Base R 循环(无需额外包)
通过提取疾病前缀批量处理,适合不想加载第三方包的场景:
# 提取所有唯一的疾病前缀(匹配`xxx_scm`格式) disease_prefixes <- unique(sub("\\.\\d+$", "", colnames(df4))) disease_prefixes <- disease_prefixes[grepl("_scm", disease_prefixes)] # 循环计算每个疾病的行均值 for(prefix in disease_prefixes) { # 匹配当前前缀对应的所有题项列 target_cols <- grep(paste0("^", prefix, "\\."), colnames(df4), value = TRUE) # 计算行均值,na.rm=TRUE表示忽略缺失值,按需调整 df4[[paste0(prefix, "_mean")]] <- rowMeans(df4[, target_cols], na.rm = TRUE) }
方法2:tidyverse 风格实现(dplyr + stringr)
代码更简洁,适合熟悉tidyverse生态的用户:
library(dplyr) library(stringr) df4 <- df4 %>% # 针对所有符合规则的题项列,计算对应疾病的行均值 mutate(across(matches("_scm\\.\\d+"), .fns = list(mean = ~ rowMeans(select(cur_data(), starts_with(str_remove(cur_column(), "\\.\\d+$"))), na.rm = TRUE)), .names = "{str_remove(.col, '\\.\\d+')}_mean")) %>% # 去重重复生成的均值列(每个题项都会生成一次,保留唯一的均值列) select(-matches("_scm\\.\\d+_mean_\\d+")) %>% rename_with(~ str_remove(., "_mean_\\d+"), matches("_scm_mean_\\d+"))
方法3:data.table 实现(大数据集最优)
对于超大规模数据集,data.table的效率远高于base R和tidyverse:
library(data.table) setDT(df4) # 筛选所有目标题项列 target_cols <- colnames(df4)[grepl("_scm\\.\\d+", colnames(df4))] # 提取唯一的疾病前缀 disease_prefixes <- unique(sub("\\.\\d+$", "", target_cols)) # 批量计算行均值 for(prefix in disease_prefixes) { df4[, paste0(prefix, "_mean") := rowMeans(.SD, na.rm = TRUE), .SDcols = grep(paste0("^", prefix, "\\."), target_cols, value = TRUE)] }
内容的提问来源于stack exchange,提问作者Lea
相关产品推荐
相关产品推荐

