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

为何dplyr::slice_min()函数性能表现异常缓慢?

为什么dplyr::slice_min()提取组内最小值对应行时性能远低于排序或summarize方法?

假设有一个数据框dat,包含group变量,每组有一个或多个x观测值,且组内x无重复值。提取每组中x取最小值对应观测值的一种方法是使用dplyr::slice_min()。

我认可slice_min()能清晰表达意图,但它的性能常常异常缓慢,如下测试所示。我原以为在组内对x值排序(逻辑上比找最小值更复杂)会更慢,为何排序方法反而快这么多?甚至我用summarize()的特殊写法都快得多!

更具体地说,我希望在组数n趋于无穷大且每组观测数为O(1)时,仍能保持良好的处理性能。


测试代码

library(dplyr)
library(microbenchmark)

# 模拟数据。y是我们想要保留的、对应x最小值的其他变量
set.seed(1)
n <- 5e3
k <- 1 + rpois(n, 1)
dat <- data.frame(
  group = rep(1:n, k), 
  x = rnorm(sum(k)),
  y = sample(letters, sum(k), replace = TRUE)
)

# 获取每组内x最小的观测行
microbenchmark(
  slice = dat |>
    group_by(group) |>
    slice_min(x) |>
    ungroup(),
  arrange = dat |>
    arrange(group, x) |>
    filter(!duplicated(group)),
  summarize = dat |>
    group_by(group) |>
    summarize(i = which.min(x), across(everything(), \(v) v[i])) |>
    select(!i),
  times = 10
)

性能测试结果

# 单位:毫秒
#       expr        min         lq       mean    median         uq        max neval
#      slice 556.812802 625.876500 655.172451 632.45395 646.751201 909.931001    10
#    arrange   3.148302   3.209201   3.348941   3.34970   3.441501   3.663301    10
#  summarize  37.503501  37.946201  53.125181  38.17705  38.911001 127.843800    10

性能差异的核心原因

  1. slice_min()的内部损耗:
    slice_min()是逐组单独执行排序并提取首行,当组数极多时,每个分组的初始化、排序校验等流程开销会被不断累积。另外它还包含了处理重复值、支持多参数的通用逻辑,这些在简单场景下反而成了不必要的性能负担。

  2. arrange()+filter的全局优化:
    arrange()基于底层高效的C++算法做全局排序,向量化操作的效率远高于逐组处理。排序后每组最小值行自然排在组内首位,再用!duplicated(group)保留每组第一行,这个步骤也是向量化的,几乎无额外开销。当每组观测数很少时,全局排序的时间复杂度(O(M log M))远低于逐组处理的复杂度(O(K*m log m)),性能优势明显。

  3. summarize()的中间定位:
    这种写法逐组调用which.min(x)找最小值索引,再提取对应行。which.min()是轻量向量操作,比逐组排序快,但仍属于逐组执行,所以性能介于前两者之间。

大组数场景的优化建议

  • 优先用arrange()+filter(!duplicated()):在每组观测数少的场景下性能碾压其他方法,代码简洁性也不错。
  • 可选data.table实现:DT[, .SD[which.min(x)], by = group]的分组处理基于底层优化,性能接近arrange方法,适合严格依赖分组逻辑的场景。
  • 仅在可读性优先时用slice_min():比如团队协作中,它的语义最清晰,但要注意大组数场景的性能问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.07 19:20:33