逐行创建R数据帧

Dav*_*d B 103 r list dataframe

我想在R中逐行构建一个数据帧.我已经做了一些搜索,我想出的是建议创建一个空列表,保留一个列表索引标量,然后每次添加到列表单行数据帧并将列表索引提前一个.最后,do.call(rbind,)在名单上.

虽然这有效,但看起来非常麻烦.是否有更简单的方法来实现相同的目标?

显然,我指的是我不能使用某些apply函数并明确需要逐行创建数据帧的情况.至少,有没有办法push进入列表的末尾而不是显式跟踪最后使用的索引?

Dir*_*tel 92

您可以通过追加或使用逐行增长它们rbind().

这并不意味着你应该这样做.动态增长的结构是在R中编码最低效的方法之一.

如果可以,请预先分配整个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
Run Code Online (Sandbox Code Playgroud)

然后在您的操作期间一次插入行

DF[i, ] <- list(1.4, "foo")
Run Code Online (Sandbox Code Playgroud)

这应该适用于任意data.frame并且效率更高.如果你超过N,你总是可以在最后收缩空行.

  • 你是不是要把N而不是10,并列出(1.4,"foo")而不是c(1.4,"foo"),以免强制1.4进入字符模式? (6认同)
  • `data.table`似乎比使用data.frames预分配更快.在此测试:http://stackoverflow.com/a/11486400/636656 (4认同)

mbq*_*mbq 47

可以添加行到NULL:

df<-NULL;
while(...){
  #Some code that generates new row
  rbind(df,row)->df
}
Run Code Online (Sandbox Code Playgroud)

例如

df<-NULL
for(e in 1:10) rbind(df,data.frame(x=e,square=e^2,even=factor(e%%2==0)))->df
print(df)
Run Code Online (Sandbox Code Playgroud)

  • 它输出矩阵,而不是数据帧 (3认同)

hat*_*rix 9

这是一个如何do.call(rbind,)Map()[类似lapply()] 的输出上使用的愚蠢的例子

> 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"
Run Code Online (Sandbox Code Playgroud)

我经常使用这个结构.


All*_*kes 8

我之所以如此喜欢Rcpp,是因为我并不总是了解R Core的想法,而且通常使用Rcpp,我不需要.

哲学上说,你在与问候的功能模式,它试图以确保每一个价值罪的状态出现独立每隔价值; 更改一个值不应该导致另一个值的可见更改,使用指针在C中共享表示的方式.

当功能性编程发出信号表示小型船只移开时,问题就出现了,小型工艺人员回答"我是一座灯塔".在此期间对要处理的大对象进行一系列小的更改会使您成为灯塔区域的正方形.

在C++ STL中,push_back()是一种生活方式.它不会尝试是功能性的,但它确实尽力满足常见的编程风格有效.

在幕后有些聪明,你有时可以在每个世界中安排一只脚.基于快照的文件系统就是一个很好的例子(它是从诸如联合安装之类的概念发展而来的,它也是双方的一部分).

如果R Core想要这样做,底层矢量存储可以像union mount一样运行.对向量存储的一个引用可能对下标有效1:N,而对同一存储的另一个引用对下标有效1:(N+1).可能有任何保留存储尚未被有效引用,但方便快捷push_back().在超出任何现有引用认为有效的范围之外时,不违反功能概念.

最终以递增方式追加行,您的预留存储空间不足.你需要创建所有东西的新副本,存储乘以一些增量.我使用的STL实现在扩展分配时倾向于将存储乘以2.我以为我在R Internals中读到有一个内存结构,其中存储增加了20%.无论哪种方式,增长操作都以相对于附加元素总数的对数频率发生.在摊销的基础上,这通常是可以接受的.

作为幕后花样,我看到了更糟.每次push_back()在数据帧上添加新行时,都需要复制顶级索引结构.新行可以附加到共享表示,而不会影响任何旧的功能值.我甚至认为它不会使垃圾收集器复杂化; 因为我不建议push_front()所有引用都是对分配的向量存储的前面的前缀引用.