Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/r/66.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
R apply()很慢-如何让它更快,或者我的替代方案是什么?_R_Apply_R Faq - Fatal编程技术网

R apply()很慢-如何让它更快,或者我的替代方案是什么?

R apply()很慢-如何让它更快,或者我的替代方案是什么?,r,apply,r-faq,R,Apply,R Faq,我有一个相当大的数据帧,大约有1000万行。它有x和y列,我想要的是计算 hypot <- function(x) {sqrt(x[1]^2 + x[2]^2)} hypop使用(my_数据,sqrt(x^2+y^2))怎么样 正如所料,with()解决方案和列索引解决方案a la Tyler Rinker本质上是相同的hypot2的速度是原始hypot的两倍(但仍比矢量化解决方案慢150倍左右)。正如OP已经指出的,编译没有多大帮助。虽然Ben Bolkers的答案很全面,但我将解释避

我有一个相当大的数据帧,大约有1000万行。它有
x
y
列,我想要的是计算

hypot <- function(x) {sqrt(x[1]^2 + x[2]^2)}
hypop使用(my_数据,sqrt(x^2+y^2))
怎么样


正如所料,
with()
解决方案和列索引解决方案a la Tyler Rinker本质上是相同的
hypot2
的速度是原始
hypot
的两倍(但仍比矢量化解决方案慢150倍左右)。正如OP已经指出的,编译没有多大帮助。

虽然Ben Bolkers的答案很全面,但我将解释避免在data.frames上应用
的其他原因

apply
将把
data.frame
转换为矩阵。这将创建一个副本(浪费时间和内存),并可能导致意外的类型转换

考虑到您有1000万行数据,我建议您查看
data.table
包,它可以让您在内存和时间方面高效地完成工作


例如,使用
traceem

x <- apply(d,1, hypot2)
tracemem[0x2f2f4410 -> 0x2f31b8b8]: as.matrix.data.frame as.matrix apply 
4份有1000万排,可能会在某个时候咬到你

如果我们将
一起使用,则如果我们指定给向量,则不涉及
复制

y <- with(d, sqrt(x^2 + y^2))
现在,如果使用
data.table
:=
通过引用分配(无复制)


R是矢量化的,因此您可以使用以下内容,当然可以插入您自己的矩阵

X = t(matrix(1:4, 2, 2))^2
>      [,1] [,2]
 [1,]    1    4
 [2,]    9   16

rowSums(X)^0.5

很好,效率很高:)

矢量是一件美丽的事情:)@Ricardosporta,我想那只是噪音——时差大约是0.007秒…@BenBolker。我很好奇,所以我跑了100x250次:
$
各快45%,
[
只有10%左右。如果
m@CherSania:当我看到你上面的第一条评论时,我笑了,因为在使用R一段时间后,我无法习惯其他语言没有矢量化。每次我现在需要矢量化时,我都在想“真的,我必须自己编写这个循环吗?”
                       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
x <- apply(d,1, hypot2)
tracemem[0x2f2f4410 -> 0x2f31b8b8]: as.matrix.data.frame as.matrix apply 
d$x <- apply(d,1, hypot2)
tracemem[0x2f2f4410 -> 0x2ee71cb8]: as.matrix.data.frame as.matrix apply 
tracemem[0x2f2f4410 -> 0x2fa9c878]: 
tracemem[0x2fa9c878 -> 0x2fa9c3d8]: $<-.data.frame $<- 
tracemem[0x2fa9c3d8 -> 0x2fa9c1b8]: $<-.data.frame $<- 
y <- with(d, sqrt(x^2 + y^2))
d$y <- with(d, sqrt(x^2 + y^2))
tracemem[0x2fa9c1b8 -> 0x2faa00d8]: 
tracemem[0x2faa00d8 -> 0x2faa0f48]: $<-.data.frame $<- 
tracemem[0x2faa0f48 -> 0x2faa0d08]: $<-.data.frame $<- 
 library(data.table)
 DT <- data.table(d)



tracemem(DT)
[1] "<0x2d67a9a0>"
DT[,y := sqrt(x^2 + y^2)]
 DT[, rowid := .I] # previous option: DT[, rowid := seq_len(nrow(DT))]
 DT[, y2 := sqrt(x^2 + y^2), by = rowid]
X = t(matrix(1:4, 2, 2))^2
>      [,1] [,2]
 [1,]    1    4
 [2,]    9   16

rowSums(X)^0.5