如何在R的data.table中对两组列执行不同的汇总操作?
问题描述
将data.frame转为data.table后,无法复现原dplyr的分组汇总逻辑,需求如下:
- 分组依据:
Player、Tier、Sex - 计算规则:
Min列:sum(Min, na.rm=TRUE)/90后取整non_percent类列:sum(列值, na.rm=TRUE)/Min后保留两位小数percent类列:mean(列值, na.rm=TRUE)后保留两位小数
原dplyr代码:
player_matchLogs %>% group_by(Player, Tier, Sex) %>% summarize( Min = round(sum(Min, na.rm = TRUE) / 90), across(non_percent, ~ round(sum(.x, na.rm = TRUE) / Min, 2)), across(percent, ~ round(mean(.x, na.rm = TRUE), 2)) )
数据集预览:
> glimpse(player_matchLogs) Rows: 41 Columns: 130 $ League <chr> "Premier League", "Pr… $ Match_Date <chr> "2023-08-11", "2023-0… ...(其余列省略) $ Rival_Goals <dbl> 0, 0, 1, 1, 1, 0, 2, …
解决方案
用data.table实现相同逻辑的代码如下,核心是利用data.table的分组语法和代码块执行多行计算逻辑:
library(data.table) # 将data.frame转为data.table(若未转换) setDT(player_matchLogs) # ********* 关键:替换为实际的non_percent和percent列名 ********* non_percent <- c("Rival_Goals", "...") # 示例列,替换成你的非百分比列 percent <- c("...") # 替换成你的百分比列 # 分组汇总 result <- player_matchLogs[, { # 计算中间变量:总分钟数和取整后的Min total_min <- sum(Min, na.rm = TRUE) min_calc <- round(total_min / 90) # 处理non_percent类列:sum后除以min_calc,保留两位小数 non_percent_res <- lapply(.SD[, non_percent, with = FALSE], function(col) { round(sum(col, na.rm = TRUE) / min_calc, 2) }) # 处理percent类列:取均值后保留两位小数 percent_res <- lapply(.SD[, percent, with = FALSE], function(col) { round(mean(col, na.rm = TRUE), 2) }) # 合并结果:Min + non_percent结果 + percent结果 c(list(Min = min_calc), non_percent_res, percent_res) }, by = .(Player, Tier, Sex), .SDcols = c("Min", non_percent, percent)]
关键说明
- 列定义:必须准确指定
non_percent和percent的列名,对应dplyr中across的列分组 - 中间变量:用
{}在j参数中编写多行代码,先计算total_min和min_calc,避免重复计算 - 效率优化:
.SDcols只传入需要处理的列,减少内存占用,提升大数据集的处理速度 - 语法细节:
with=FALSE用于在.SD中按列名子集化,lapply遍历目标列执行计算
内容的提问来源于stack exchange,提问作者Lucas Varela
相关产品推荐
相关产品推荐

