gpt4 book ai didi

r - 写入多行数据帧非常慢

转载 作者:行者123 更新时间:2023-12-04 19:05:59 25 4
gpt4 key购买 nike

让我们考虑以下三个数据框:

toto.small  <- data.frame(col1=rep(1,850), col2=rep(2,850))
toto.medium <- data.frame(col1=rep(1,85000), col2=rep(2,85000))
toto.big <- data.frame(col1=rep(1,850000), col2=rep(2,850000))

以及以下时间:
system.time(for(i in 1:100) { toto.small[i,2] <- 3 })
user system elapsed
0.004 0.000 0.006

system.time(for(i in 1:100) { toto.medium[i,2] <- 3 })
user system elapsed
0.088 0.000 0.087

system.time(for(i in 1:100) { toto.big[i,2] <- 3 })
user system elapsed
2.248 0.000 2.254

迭代大数据帧比小数据帧慢两个数量级。
这些循环只是在内存中写入 100 个预先分配的元素;时间甚至不应该取决于数据帧的总长度。

有谁知道这是什么原因?

我仍然在使用数据表和应用函数时得到类似的时间差异。

编辑 1:R 3.0.2 与 R 3.1

对于那些好奇的人,这里是使用 R v. 3.1 和 3.0.2 的 data.table 和 data.frame 的计时(我分别测量了 3 次):

R 3.0.2
      type   size time1 time2 time3
data frame small 0.005 0.005 0.005
data frame medium 0.074 0.077 0.075
data frame big 3.184 3.373 3.101
data table small 0.048 0.048 0.047
data table medium 0.073 0.068 0.066
data table big 0.615 0.621 0.593

3.1
      type   size time1 time2 time3
data frame small 0.004 0.004 0.004
data frame medium 0.021 0.020 0.022
data frame big 0.221 0.207 0.243
data table small 0.055 0.055 0.055
data table medium 0.076 0.076 0.076
data table big 0.705 0.699 0.663

R 3.1 速度更快,但仍然有些慢;数据表也一样。

编辑 2:使用函数集

R 3.1.0 上的相同数字,使用函数“set”而不是“[]”运算符
      type   size        time1        time2        time3
data frame small 0.0249999999 0.0020000000 0.0009999999
data frame medium 0.0010000000 0.0009999999 0.0010000000
data frame big 0.0010000000 0.0000000000 0.0009999999
data table small 0.0009999999 0.0209999999 0.0000000000
data table medium 0.0009999999 0.0009999999 0.0010000000
data table big 0.0000000000 0.0029999999 0.0009999999

这完全解决了性能问题。

最佳答案

您的代码很慢,因为函数 [.<-data.frame每次修改对象时都会复制底层对象。

如果您跟踪内存使用情况,它就会变得清晰:

tracemem(toto.big)
system.time({
for(i in 1:100) { toto.big[i,2] <- 3 }
})


tracemem[0x000000001d416b58 -> 0x000000001e08e9f8]: system.time
tracemem[0x000000001e08e9f8 -> 0x000000001e08eb10]: [<-.data.frame [<- system.time
tracemem[0x000000001e08eb10 -> 0x000000001e08ebb8]: [<-.data.frame [<- system.time
tracemem[0x000000001e08ebb8 -> 0x000000001e08e7c8]: system.time
tracemem[0x000000001e08e7c8 -> 0x000000001e08e758]: [<-.data.frame [<- system.time
tracemem[0x000000001e08e758 -> 0x000000001e08e800]: [<-.data.frame [<- system.time
....
tracemem[0x000000001e08e790 -> 0x000000001e08e838]: system.time
tracemem[0x000000001e08e838 -> 0x000000001e08eaa0]: [<-.data.frame [<- system.time
tracemem[0x000000001e08eaa0 -> 0x000000001e08e790]: [<-.data.frame [<- system.time
user system elapsed
4.31 1.01 5.29

要解决此问题,最好的操作是仅修改数据框一次:
untracemem(toto.big)

system.time({
toto.big[1:100, 2] <- 5
})

user system elapsed
0.02 0.00 0.02

在那些在循环中计算值(或 lapply )更方便的情况下,您可以在循环中对向量执行计算,然后在一个向量化分配中分配到数据帧中:
system.time({
newvalues <- numeric(100)
for(i in 1:100)newvalues[i] <- rnorm(1)
toto.big[1:100, 2] <- newvalues
})

user system elapsed
0.02 0.00 0.02

您可以查看 <-.data.frame 的代码通过输入 `<-.data.frame`进入你的控制台。

关于r - 写入多行数据帧非常慢,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24569532/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com