R语言批量对数据框成对列做除法生成新列的方案
R语言批量计算配对列除法实现方案
问题说明
使用如下代码构建示例数据集:
val_a <- c("2", "4", "6", "8") divide_a <- c(1, 2, 3, 4) val_b <- c("62", "42", "56", "28") divide_b <- c(11, 12, 22, 44) val_c <- c("652", "142", "546", "298") divide_c <- c(74, 23, 112, 64) df <- as.data.frame(cbind(val_a, divide_a, val_b, divide_b, val_c, divide_c))
代码运行后得到的数据框结构如下:
val_a divide_a val_b divide_b val_c divide_c 1 2 1 62 11 652 74 2 4 2 42 12 142 23 3 6 3 56 22 546 112 4 8 4 28 44 298 64
需求为对所有配对的val_*列、divide_*列做除法运算,生成对应result_*结果列,预期输出结构如下:
val_a divide_a val_b divide_b val_c divide_c result_a result_b result_c 1 2 1 62 11 652 74 2 5,6 8,8 2 4 2 42 12 142 23 2 3,5 6,2 3 6 3 56 22 546 112 2 2,5 4,9 4 8 4 28 44 298 64 2 0,6 4,7
原有for循环实现存在两个问题:
- 循环逐一遍历每列与下一列做除法,未跳过非配对列,例如会错误将
divide_a列与val_b列做运算 - 生成的新列未按规则正确命名
实际使用的数据框包含超过1000列,无法手动逐列计算,需要高效批量实现方案。
实现方案
方案1:按列位置匹配(列顺序固定为val、divide交替时使用,性能最高)
不需要加载第三方包,直接利用R的矩阵运算做批量计算,比逐行逐列循环快数十倍,千列级数据集秒出结果:
# 第一步:将所有存储为字符类型的数值列转为数值型,避免计算报错 df[] <- lapply(df, as.numeric) # 第二步:按固定步长提取所有val列、对应divide列的位置 val_col_pos <- seq(1, ncol(df), by = 2) divide_col_pos <- val_col_pos + 1 # 第三步:批量做除法运算 result_df <- df[, val_col_pos] / df[, divide_col_pos] # 第四步:自动匹配结果列名 colnames(result_df) <- gsub("^val_", "result_", colnames(result_df)) # 第五步:将结果拼接到原数据框 df <- cbind(df, result_df)
如果需要和示例一样用逗号作为小数分隔符,追加格式化代码即可:
df[, colnames(result_df)] <- lapply( df[, colnames(result_df)], function(x) gsub("\\.", ",", as.character(round(x, 1))) )
方案2:按列名匹配(列顺序不固定时使用,鲁棒性最强)
如果数据集列顺序可能被打乱、或者配对列中间穿插了其他无关列,直接按列名后缀做匹配,不会出现配对错误:
# 转数值型 df[] <- lapply(df, as.numeric) # 提取所有val列的后缀标识 col_suffix <- gsub("^val_", "", grep("^val_", colnames(df), value = TRUE)) # 按后缀批量计算 for(s in col_suffix){ res_col <- paste0("result_", s) df[[res_col]] <- df[[paste0("val_", s)]] / df[[paste0("divide_", s)]] # 需要逗号小数分隔符就打开下面注释 # df[[res_col]] <- gsub("\\.", ",", as.character(round(df[[res_col]], 1))) }
内容的提问来源于stack exchange,提问作者Asparagus
相关产品推荐
相关产品推荐

