我有一个很大的数据框,大约有一千万行。它具有列x
和y
,我要计算的是
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所指出的,编译没有太大帮助。