考虑一个带有
dat
变量的数据框 group
,并且每组有一个或多个 x
观察值。假设组内 x
中没有关系。提取使每个 x
内的 group
最小化的观察结果的一种方法是使用 dplyr::slice_min()
。
我喜欢
slice_min()
清楚地表达了我的意图,但它通常很慢,如下所示。在组内排列 x
的值时,我预计性能会较慢(比查找最小值更简单)。怎么速度这么快?即使我奇怪地使用下面的summarize()
也快得多!
更具体地说,我希望在 n 个组和每组 O(1) 次观察中保持良好的性能,因为 n 趋于无穷大。
library(dplyr)
library(microbenchmark)
# Simulate data. y is some other variable whose value we'd like to keep at the
# minimum of 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)
)
# Obtain observation that minimizes x within each group
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
)
性能:
# Unit: milliseconds
# 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
与 slice_max 相关的 github 问题有一位
dplyr
的作者建议对 arrange
方法进行变体,甚至更快:
https://github.com/tidyverse/dplyr/issues/6783
arrange2 = dat |>
arrange(x) |>
distinct(group)