如何在R中用循环、dplyr、data.table及apply生成行和新列
解决方案
一、dplyr 循环实现的正确写法
你之前使用的mutate_是dplyr旧版本的非标准评估函数,现已不推荐。以下是适配新版dplyr的循环写法,同时解决NA值处理的问题:
library(dplyr) df <- data.frame(A=c(22, 25, 29, 13, 22, 30), B=c(12, 10, 6, 6, 8, 11), C=c(NA, 15, 15, 18, 22, 13)) for(i in 1:2) { col_name <- paste0("a", i) df <- df %>% mutate(!!col_name := rowSums(select(., 1:(1+i)), na.rm = TRUE)) }
说明:
- 用
!!解析动态生成的列名,实现动态赋值 select(., 1:(1+i))在管道上下文里引用当前数据框的前1+i列,避免循环中重复调用外部df引发的问题na.rm=TRUE确保NA值不影响求和结果
二、data.table 循环实现的正确写法
data.table支持原地修改,无需重新赋值给原对象,同时要修正列选择语法和NA处理:
library(data.table) df <- data.table(A=c(22, 25, 29, 13, 22, 30), B=c(12, 10, 6, 6, 8, 11), C=c(NA, 15, 15, 18, 22, 13)) for(i in 1:2) { col_name <- paste0("a", i) df[, (col_name) := rowSums(.SD[, 1:(1+i), with=FALSE], na.rm = TRUE)] }
说明:
(col_name)用于传递动态列名,实现新列的赋值.SD代表当前数据框的子集,with=FALSE允许按位置索引列- 添加
na.rm=TRUE处理NA值
三、apply 函数实现方案(非循环最优解)
如果不需要循环,直接用apply或rowSums批量生成目标列,效率更高:
方式1:apply逐行计算
df <- data.frame(A=c(22, 25, 29, 13, 22, 30), B=c(12, 10, 6, 6, 8, 11), C=c(NA, 15, 15, 18, 22, 13)) # 计算前2列、前3列的行和,转置后转为数据框 sum_cols <- t(apply(df, 1, function(x) c(sum(x[1:2], na.rm=TRUE), sum(x[1:3], na.rm=TRUE)))) colnames(sum_cols) <- c("a1", "a2") # 合并到原数据框 df <- cbind(df, sum_cols)
方式2:rowSums批量生成
这是最简洁的方案,直接一次性生成所有需要的列:
df <- data.frame(A=c(22, 25, 29, 13, 22, 30), B=c(12, 10, 6, 6, 8, 11), C=c(NA, 15, 15, 18, 22, 13)) df <- cbind(df, a1 = rowSums(df[,1:2], na.rm=TRUE), a2 = rowSums(df[,1:3], na.rm=TRUE))
内容的提问来源于stack exchange,提问作者catin
相关产品推荐
相关产品推荐

