如何在DataFrame指定列中逐行计算最小值并生成新列?
在R的DataFrame中对指定列逐行执行公式计算的方法
咱们就用你给出的商店玩具价格数据集来展开说明,先把示例数据放出来方便参考:
dfData <- data.frame(article = c("Fix", "Foxi", "Stan", "Olli", "Barbie", "Ken", "Hulk"), priceToys1 = c(10, NA, 10.5, NA, 10.7, 11.2, 12.0), priceAllToys = c(NA, 11.4, NA, 11.9, 11.7, 11.1, NA), price123Toys = c(12, 12.4, 12.7, NA, NA, 11.0, 12.1))
你已经用到的基础R方法:apply()
你写的这段代码其实已经完美实现了需求,咱们拆解下它的逻辑:
dfData$MinPrice <- apply(dfData[, grep("price", colnames(dfData))], 1, FUN=min, na.rm = TRUE)
grep("price", colnames(dfData)):先筛选出所有列名包含price的列,拿到它们的索引;dfData[, 上述索引]:提取出这些目标列组成的子数据集;apply(..., 1, FUN=min, na.rm=TRUE):MARGIN=1表示按行执行操作,对每一行调用min函数,na.rm=TRUE用来忽略缺失值NA,避免计算结果变成NA。
更贴合现代R工作流的方法:dplyr(tidyverse系列)
如果你平时习惯用tidyverse工具包,用rowwise() + c_across()的组合会更直观,代码可读性也更强:
library(dplyr) dfData <- dfData %>% rowwise() %>% # 告诉dplyr接下来的操作要按行执行 mutate(MinPrice_dplyr = min(c_across(starts_with("price")), na.rm = TRUE)) %>% # 对所有以price开头的列取最小值 ungroup() # 取消按行分组的状态,避免影响后续操作
这里starts_with("price")是tidyselect语法,用来筛选列,你也可以用contains("price")和之前的grep逻辑一致。
适合大数据集的高效方法:data.table
如果你的数据集非常大,追求计算速度的话,data.table是更好的选择,它的逐行操作效率远高于基础R和dplyr:
library(data.table) # 先把普通DataFrame转成data.table格式 setDT(dfData) # 新增列,对所有列名含price的列逐行取最小值 dfData[, MinPrice_dt := do.call(pmin, c(.SD, na.rm = TRUE)), .SDcols = patterns("price")]
.SDcols = patterns("price"):指定要操作的列(列名匹配price的);do.call(pmin, c(.SD, na.rm = TRUE)):pmin是向量化的最小值函数,结合do.call对每一行的所有目标列计算最小值,na.rm=TRUE处理缺失值。
总结
- 基础R的
apply():无需额外安装包,适合小数据集快速实现; dplyr方法:代码风格统一,可读性强,适合tidyverse用户;data.table方法:性能最优,处理十万级以上数据时优势明显。
内容的提问来源于stack exchange,提问作者Juppes
相关产品推荐
相关产品推荐

