我想在R中逐行构造一个数据帧。我做了一些搜索,然后想到的是创建一个空列表,保持列表索引标量,然后每次添加到该列表是一个单行数据帧,并将列表索引前移一个。最后,在列表上为do.call(rbind,)
。
虽然这有效,但似乎很麻烦。没有简单的方法可以实现相同的目标吗?
显然,我指的是我无法使用某些apply
函数,并且明确需要逐行创建数据帧的情况。至少,有一种方法可以使push
进入列表的末尾,而不是明确跟踪最后使用的索引吗?
如果可以,请预先分配整个data.frame:
N <- 1e4 # total number of rows to preallocate--possibly an overestimate
DF <- data.frame(num=rep(NA, N), txt=rep("", N), # as many cols as you need
stringsAsFactors=FALSE) # you don't know levels yet
然后在操作过程中一次插入行
DF[i, ] <- list(1.4, "foo")
这应该适用于任意data.frame并且效率更高。如果您超过N,则总是可以在末尾缩小空白行。
df<-NULL;
while(...){
#Some code that generates new row
rbind(df,row)->df
}
例如
df<-NULL
for(e in 1:10) rbind(df,data.frame(x=e,square=e^2,even=factor(e%%2==0)))->df
print(df)
> DF <- do.call(rbind,Map(function(x) data.frame(a=x,b=x+1),x=1:3))
> DF
x y
1 1 2
2 2 3
3 3 4
> class(DF)
[1] "data.frame"
我经常使用这种结构。
出现独立于其他所有值;更改一个值永远不会导致另一个值的可见更改,就像您在C语言中共享指针的方式一样。
[当函数式编程向小型飞船发出信号,而小型飞船回答“我是灯塔”时,就会出现问题。同时,对要处理的大对象进行一系列小改动,可以使您进入灯塔领域。
在C ++ STL中,push_back()
是一种生活方式。它并没有试图发挥功能,但是确实试图适应常见的编程习惯有效地
。[在幕后有些聪明,您有时可以安排在每个世界中一只脚走路。基于快照的文件系统就是一个很好的例子(它是从联合安装等概念发展而来的,该概念也同时包含了双方)。
如果R Core想要这样做,则底层向量存储可以像联合安装那样工作。对向量存储的一种引用可能对下标1:N
有效,而对相同存储的另一种引用对下标1:(N+1)
有效。可能存在尚未方便快速引用push_back()
的任何东西有效引用的保留存储。在任何现有参考认为有效的范围之外进行附加时,都不会违反功能概念。 最终最终以增量方式追加行,将耗尽保留的存储空间。您需要创建所有内容的新副本,并将存储空间乘以一定的增量。我使用的STL实现在扩展分配时倾向于将存储量乘以2。我以为我在R Internals中读到了一种内存结构,其中存储量增加了20%。无论哪种方式,生长操作都相对于附加元素总数以对数频率进行。按摊销基准,这通常是可以接受的。
随着幕后花招的流传,我看到的更糟。每次将新行push_back()
插入数据帧时,都需要复制一个顶层索引结构。新行可以追加到共享表示中,而不会影响任何旧功能值。我什至不认为这会使垃圾收集器复杂化。因为我不建议push_front()
,所以所有引用都是已分配向量存储区前面的前缀引用。