List 逐行创建R数据帧

List 逐行创建R数据帧,list,r,dataframe,List,R,Dataframe,我想在R中逐行构造一个数据帧。我做了一些搜索,我想到的只是建议创建一个空列表,保留一个列表索引标量,然后每次向列表中添加一个单行数据帧,并将列表索引前进一个。最后,在列表中,do.call(rbind,) 虽然这是可行的,但似乎非常麻烦。难道没有更简单的方法来实现同样的目标吗 显然,我指的是不能使用一些apply函数并明确需要逐行创建数据帧的情况。至少,有没有一种方法可以将推到列表的末尾,而不是显式地跟踪最后使用的索引?可以将行添加到NULL: df<-NULL; while(...){

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

虽然这是可行的,但似乎非常麻烦。难道没有更简单的方法来实现同样的目标吗


显然,我指的是不能使用一些
apply
函数并明确需要逐行创建数据帧的情况。至少,有没有一种方法可以将
推到列表的末尾,而不是显式地跟踪最后使用的索引?

可以将行添加到
NULL

df<-NULL;
while(...){
  #Some code that generates new row
  rbind(df,row)->df
}
dfdf
}
比如说

df<-NULL
for(e in 1:10) rbind(df,data.frame(x=e,square=e^2,even=factor(e%%2==0)))->df
print(df)
dfdf
打印(df)

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

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

如果可以,请提前分配整个数据。帧:

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

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

>测向
xy
1 1 2
2 2 3
3 3 4
>等级(DF)
[1] “数据帧”

我经常使用这种结构。

我之所以如此喜欢Rcpp,是因为我并不总是了解R Core的思维方式,而使用Rcpp,我通常不需要了解

从哲学上讲,你在功能范式方面处于一种罪恶的状态,它试图确保每一个价值都独立于其他价值;更改一个值不应导致另一个值发生可见的更改,就像您在C中使用指针共享表示时所得到的那样

当函数式编程发出信号让小艇让路,小艇回答“我是灯塔”时,问题就出现了。对一个你想处理的大物体做一系列的小改变,这会让你进入灯塔的领域

<>在C++ STL中,<代码> PuxOffBeD()/Cuth>是一种生活方式。它并不试图实现功能性,但它确实试图有效地适应常见的编程习惯

有了一些幕后的聪明,你有时可以安排在每个世界都有一只脚。基于快照的文件系统就是一个很好的例子(它是从联合挂载(unionmounts)等概念演变而来的,这种挂载也适用于双方)

如果R Core想这样做,底层向量存储可以像联合挂载一样工作。对向量存储器的一个引用可能对下标
1:N
有效,而对同一存储器的另一个引用对下标
1:(N+1)
有效。可能存在未被有效引用的保留存储,但方便快速
推回()
。在任何现有引用认为有效的范围之外追加时,不会违反函数概念

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


随着幕后花招的发展,我看到了更糟的情况。每次
push_back()。新行可以附加到共享表示上,而不会影响任何旧的函数值。我甚至不认为这会使垃圾收集器复杂化;因为我不是建议
push_front()
所有引用都是对已分配向量存储前端的前缀引用

如果有注定要成为行的向量,请使用
c()
将它们连接起来,将它们逐行传递到矩阵,然后将该矩阵转换为数据帧

例如,行

dummydata1=c(2002,10,1,12.00,101,426340.0,4411238.0,3598.0,0.92,57.77,4.80,238.29,-9.9)
dummydata2=c(2002,10,2,12.00,101,426340.0,4411238.0,3598.0,-3.02,78.77,-9999.00,-99.0,-9.9)
dummydata3=c(2002,10,8,12.00,101,426340.0,4411238.0,3598.0,-5.02,88.77,-9999.00,-99.0,-9.9)
可以转换为数据帧,因此:

dummyset=c(dummydata1,dummydata2,dummydata3)
col.len=length(dummydata1)
dummytable=data.frame(matrix(data=dummyset,ncol=col.len,byrow=TRUE))
诚然,我看到了两个主要的限制:(1)这只适用于单模数据,(2)你必须知道你的最终#列才能工作(也就是说,我假设你不是在使用一个最大行长度未知的参差不齐的数组)


这个解决方案看起来很简单,但根据我在R中进行类型转换的经验,我确信它会带来新的挑战。有人能对此发表评论吗?

Dirk Eddelbuettel的答案是最好的;在这里,我只是注意到,您可以不预先指定数据框维度或数据类型,这在有多个数据类型和大量列的情况下有时很有用:

row1<-list("a",1,FALSE) #use 'list', not 'c' or 'cbind'!
row2<-list("b",2,TRUE)  

df<-data.frame(row1,stringsAsFactors = F) #first row
df<-rbind(df,row2) #now this works as you'd expect.

row1我发现了一种通过raw创建数据帧而不使用矩阵的方法

使用自动列名

df<-data.frame(
        t(data.frame(c(1,"a",100),c(2,"b",200),c(3,"c",300)))
        ,row.names = NULL,stringsAsFactors = FALSE
    )
df<-setNames(
        data.frame(
            t(data.frame(c(1,"a",100),c(2,"b",200),c(3,"c",300)))
            ,row.names = NULL,stringsAsFactors = FALSE
        ), 
        c("col1","col2","col3")
    )

df根据新行的格式,如果新行很简单并且可以在“值对”中指定,则可以使用
tibble::add_row
。或者您可以使用
dplyr::bind_rows
,“do.call(rbind,dfs)公共模式的有效实现”。

您可以使用
append()
[可能应命名为insert]或
c()
将项目添加到列表的末尾,虽然在这里对您没有帮助。R中返回数据帧的函数不多,除非您从
lappy()
Map()
,等等返回数据帧,但是您可能还想看看
aggregate()
dappy(){heR.Misc}
,以及
cast(){reshape}
查看这些函数是否无法处理您的任务(这些函数都返回数据帧)。您不是想用N代替10,用list(1.4,“foo”)代替c(1.4,“foo”)以避免
df<-data.frame(
        t(data.frame(c(1,"a",100),c(2,"b",200),c(3,"c",300)))
        ,row.names = NULL,stringsAsFactors = FALSE
    )
df<-setNames(
        data.frame(
            t(data.frame(c(1,"a",100),c(2,"b",200),c(3,"c",300)))
            ,row.names = NULL,stringsAsFactors = FALSE
        ), 
        c("col1","col2","col3")
    )