You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在R的data.table中实现分组slice_min并保留全部列

用data.table实现分组筛选最小值行并保留全部列

需求说明

拥有20万+行的大型数据集,需按hv001和hv002两列分组,筛选出每组中hv101列值最小的行,同时保留所有其他列。使用dplyr可实现需求但速度过慢,现有data.table写法仅返回分组后的最小值列,需优化写法达成目标。

样本数据

hv001 hv002 hv101 hv104 hv105
1      1     1     1     1    35
2      1     1     2     2    22
3      1     1     3     2     2
4      1     1     3     2     0
5      1     4     1     1    35
6      1     4     2     2    32
7      1     4     3     2     4
8      1     4     3     2     2
9      1     4     3     1     1
10     1     7     1     1     51

数据结构:

structure(list(hv001 = c(1, 1, 1, 1, 1, 1, 1, 1, 1, 1), hv002 = c(1, 
1, 1, 1, 4, 4, 4, 4, 4, 7), hv101 = c(1, 2, 3, 3, 1, 2, 3, 3, 
3, 1), hv104 = c(1, 2, 2, 2, 1, 2, 2, 2, 1, 1), hv105 = c(35, 
22, 2, 0, 35, 32, 4, 2, 1, 51)), row.names = c(NA, -10L), class = "data.frame")

原有实现代码

  • dplyr写法(速度慢):
df |>  
  group_by(hv001, hv002) |> 
  slice_min(hv101)
  • 现有data.table写法(仅返回最小值列):
df_dt <- as.data.table(df)
df_dt[, .(min_hv101 = min(hv101)), by = c("hv001", "hv002")]

解决方案

方法1:保留所有最小值行(与dplyr默认行为一致)

利用data.table的.SD对象(代表每个分组的子数据集),筛选出hv101等于分组内最小值的所有行,自动保留全部列:

df_dt <- as.data.table(df)
result <- df_dt[, .SD[hv101 == min(hv101)], by = .(hv001, hv002)]

样本数据运行输出:

hv001 hv002 hv101 hv104 hv105
1:     1     1     1     1    35
2:     1     4     1     1    35
3:     1     7     1     1    51

方法2:仅保留第一个最小值行(对应dplyr slice_min(n=1))

若每组只需保留第一行hv101最小的记录,使用which.min()定位行索引:

df_dt <- as.data.table(df)
result <- df_dt[, .SD[which.min(hv101)], by = .(hv001, hv002)]

效率说明

data.table的分组操作基于底层C实现,在20万+行的大型数据集上,上述写法的运行速度远快于dplyr的slice_min,同时完美满足保留全部列的需求。

内容的提问来源于stack exchange,提问作者Victor Hartman

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.05 05:45:35