我有一个很大的数据框,大约有一千万行。它具有列xy,我要计算的是

hypot <- function(x) {sqrt(x[1]^2 + x[2]^2)}


每行。使用apply会花费很多时间(大约5分钟,从较小的尺寸进行插值)和内存。

但这对我来说似乎太多了,所以我尝试了不同的方法:


编译hypot函数可将时间减少约10%
使用plyr中的函数会大大增加运行时间。


做这个事情最快的方法是什么?

最佳答案

with(my_data,sqrt(x^2+y^2))呢?

set.seed(101)
d <- data.frame(x=runif(1e5),y=runif(1e5))

library(rbenchmark)


每行有两种不同的功能,一种是利用矢量化功能:

hypot <- function(x) sqrt(x[1]^2+x[2]^2)
hypot2 <- function(x) sqrt(sum(x^2))


也尝试编译这些:

library(compiler)
chypot <- cmpfun(hypot)
chypot2 <- cmpfun(hypot2)

benchmark(sqrt(d[,1]^2+d[,2]^2),
          with(d,sqrt(x^2+y^2)),
          apply(d,1,hypot),
          apply(d,1,hypot2),
          apply(d,1,chypot),
          apply(d,1,chypot2),
          replications=50)


结果:

                       test replications elapsed relative user.self sys.self
5       apply(d, 1, chypot)           50  61.147  244.588    60.480    0.172
6      apply(d, 1, chypot2)           50  33.971  135.884    33.658    0.172
3        apply(d, 1, hypot)           50  63.920  255.680    63.308    0.364
4       apply(d, 1, hypot2)           50  36.657  146.628    36.218    0.260
1 sqrt(d[, 1]^2 + d[, 2]^2)           50   0.265    1.060     0.124    0.144
2  with(d, sqrt(x^2 + y^2))           50   0.250    1.000     0.100    0.144


正如预期的那样,with()解决方案和Tyler Rinker列索引解决方案基本相同; hypot2的速度是原始hypot的两倍(但仍比矢量化解决方案慢约150倍)。正如OP所指出的,编译没有太大帮助。

08-19 23:48