为什么 sort 比 R 中的 order 函数慢?
Why sort is slower than order function in R?
一切都在标题中。我希望 order
使用 sort
来查找向量中值的顺序。因此 sort
应该比 order
更快地对向量进行排序,但事实并非如此:
library(microbenchmark)
ss=sample(100,10000,replace=T)
microbenchmark(sort(ss))
microbenchmark(ss[order(ss)])
结果:
> microbenchmark(sort(ss))
Unit: microseconds
expr min lq mean median uq max neval
sort(ss) 141.535 144.6415 173.6581 146.358 150.2295 2531.762 100
> microbenchmark(ss[order(ss)])
Unit: microseconds
expr min lq mean median uq max neval
ss[order(ss)] 109.198 110.9865 115.6275 111.901 115.3655 197.204 100
向量较大的示例:
ss=sample(100,1e8,replace=T)
microbenchmark(sort(ss), ss[order(ss)], times = 5)
# Unit: seconds
# expr min lq mean median uq max neval
# sort(ss) 5.427966 5.431971 5.892629 6.049515 6.207060 6.346633 5
# ss[order(ss)] 3.381253 3.500134 3.562048 3.518079 3.625778 3.784997 5
因为 sort.default()
使用 order
(而不是反过来)。
function (x, decreasing = FALSE, na.last = NA, ...)
{
if (is.object(x))
x[order(x, na.last = na.last, decreasing = decreasing)]
else sort.int(x, na.last = na.last, decreasing = decreasing,
...)
}
sort
必须确定它的方法,然后在直接使用 x[order(x)]
时执行您正在一步执行的相同 x[order(x)]
调用。您可以根据需要增加输入的大小。对于整数向量,x[order(x)]
应始终优于 sort(x)
.
一年后表明,大部分差异在于 NA
值的默认处理方式。这里应该是公认的答案。
默认参数下NA
值的处理方式不同。在 sort
中,必须扫描整个向量以获取 NA
值,然后将其删除;在 order
中,它们只是放在最后。当两者都使用参数sort.last = TRUE
时,性能基本相同。
ss=sample(100,1e8,replace=T)
bench::mark(sort(ss), ss[order(ss)], sort(ss, na.last = TRUE))
# A tibble: 3 x 14
expression min mean median max `itr/sec` mem_alloc n_gc n_itr total_time result
<chr> <bch:> <bch:> <bch:> <bch:> <dbl> <bch:byt> <dbl> <int> <bch:tm> <list>
1 sort(ss) 2.610s 2.610s 2.610s 2.610s 0.383 762.940MB 0 1 2.610s <int ~
2 ss[order(~ 1.597s 1.597s 1.597s 1.597s 0.626 762.940MB 0 1 1.597s <int ~
3 sort(ss, ~ 1.592s 1.592s 1.592s 1.592s 0.628 762.940MB 0 1 1.592s <int ~
# ... with 3 more variables: memory <list>, time <list>, gc <list>
一切都在标题中。我希望 order
使用 sort
来查找向量中值的顺序。因此 sort
应该比 order
更快地对向量进行排序,但事实并非如此:
library(microbenchmark)
ss=sample(100,10000,replace=T)
microbenchmark(sort(ss))
microbenchmark(ss[order(ss)])
结果:
> microbenchmark(sort(ss))
Unit: microseconds
expr min lq mean median uq max neval
sort(ss) 141.535 144.6415 173.6581 146.358 150.2295 2531.762 100
> microbenchmark(ss[order(ss)])
Unit: microseconds
expr min lq mean median uq max neval
ss[order(ss)] 109.198 110.9865 115.6275 111.901 115.3655 197.204 100
向量较大的示例:
ss=sample(100,1e8,replace=T)
microbenchmark(sort(ss), ss[order(ss)], times = 5)
# Unit: seconds
# expr min lq mean median uq max neval
# sort(ss) 5.427966 5.431971 5.892629 6.049515 6.207060 6.346633 5
# ss[order(ss)] 3.381253 3.500134 3.562048 3.518079 3.625778 3.784997 5
因为 sort.default()
使用 order
(而不是反过来)。
function (x, decreasing = FALSE, na.last = NA, ...)
{
if (is.object(x))
x[order(x, na.last = na.last, decreasing = decreasing)]
else sort.int(x, na.last = na.last, decreasing = decreasing,
...)
}
sort
必须确定它的方法,然后在直接使用 x[order(x)]
时执行您正在一步执行的相同 x[order(x)]
调用。您可以根据需要增加输入的大小。对于整数向量,x[order(x)]
应始终优于 sort(x)
.
NA
值的默认处理方式。这里应该是公认的答案。
默认参数下NA
值的处理方式不同。在 sort
中,必须扫描整个向量以获取 NA
值,然后将其删除;在 order
中,它们只是放在最后。当两者都使用参数sort.last = TRUE
时,性能基本相同。
ss=sample(100,1e8,replace=T)
bench::mark(sort(ss), ss[order(ss)], sort(ss, na.last = TRUE))
# A tibble: 3 x 14
expression min mean median max `itr/sec` mem_alloc n_gc n_itr total_time result
<chr> <bch:> <bch:> <bch:> <bch:> <dbl> <bch:byt> <dbl> <int> <bch:tm> <list>
1 sort(ss) 2.610s 2.610s 2.610s 2.610s 0.383 762.940MB 0 1 2.610s <int ~
2 ss[order(~ 1.597s 1.597s 1.597s 1.597s 0.626 762.940MB 0 1 1.597s <int ~
3 sort(ss, ~ 1.592s 1.592s 1.592s 1.592s 0.628 762.940MB 0 1 1.592s <int ~
# ... with 3 more variables: memory <list>, time <list>, gc <list>