考虑这个变量
a = data.frame(x=1:5,y=2:6)
Run Code Online (Sandbox Code Playgroud)
当我使用替换函数更改第一个元素时a,a复制的相同大小的内存有多少次?
tracemem(a)
"change_first_element<-" = function(x, value) {
x[1,1] = value
return(x)
}
change_first_element(a) = 3
# tracemem[0x7f86028f12d8 -> 0x7f86028f1498]:
# tracemem[0x7f86028f1498 -> 0x7f86028f1508]: change_first_element<-
# tracemem[0x7f86028f1508 -> 0x7f8605762678]: [<-.data.frame [<- change_first_element<-
# tracemem[0x7f8605762678 -> 0x7f8605762720]: [<-.data.frame [<- change_first_element<-
Run Code Online (Sandbox Code Playgroud)
有四种复制操作.我知道R不会改变对象或通过引用传递(是的,有例外),但为什么有四个副本?一个副本不应该足够吗?
第2部分:
如果我以不同方式调用替换函数,则只有三个复制操作?
tracemem(a)
a = `change_first_element<-`(a,3)
# tracemem[0x7f8611f1d9f0 -> 0x7f8607327640]: change_first_element<-
# tracemem[0x7f8607327640 -> 0x7f8607327758]: [<-.data.frame [<- change_first_element<-
# tracemem[0x7f8607327758 -> 0x7f8607327800]: [<-.data.frame [<- change_first_element<-
Run Code Online (Sandbox Code Playgroud) 我正在使用RMongoDB,我需要使用查询的值填充空data.frame.结果很长,约有2百万个文件(行).
在我进行性能测试时,我发现将值写入一行的时间会增加数据帧的维度.也许这是一个众所周知的问题,我是最后一个注意到它的人.
一些代码示例:
set.seed(20140430)
nreg <- 2e3
dfres <- as.data.frame(matrix(rep(NA,nreg*7),nrow=nreg,ncol=7))
system.time(dfres[1e3,] <- c(1:5,"a","b"))
summary(replicate(10,system.time(dfres[sample(1:nreg,1),] <- c(1:5,"a","b"))[3]))
nreg <- 2e6
dfres <- as.data.frame(matrix(rep(NA,nreg*7),nrow=nreg,ncol=7))
system.time(dfres[1e3,] <- c(1:5,"a","b"))
summary(replicate(10,system.time(dfres[sample(1:nreg,1),] <- c(1:5,"a","b"))[3]))
Run Code Online (Sandbox Code Playgroud)
在我的机器上,2百万行data.frame的分配大约需要0.4秒.如果我想填充整个数据集,这是很多时间.这里进行第二次模拟以得出问题.
nreg <- seq(2e1,2e7,length.out=10)
te <- NULL
for(i in nreg){
dfres <- as.data.frame(matrix(rep(NA,i*7),nrow=i,ncol=7))
te <- c(te,mean(replicate(10,{r <- sample(1:i,1); system.time(dfres[r,] <- c(1:5,"a","b"))[3]}) ) )
}
plot(nreg,te,xlab="Number of rows",ylab="Avg. time for 10 random assignments [sec]",type="o")
#rm(nreg,dfres,te)
Run Code Online (Sandbox Code Playgroud)

问题:为什么会这样?是否有更快的方法来填充内存中的data.frame?