我经常想要将每个索引具有相同元素类型的列表转换为数据帧 . 例如,我可能有一个列表:
> my.list
[[1]]
[[1]]$global_stdev_ppb
[1] 24267673
[[1]]$range
[1] 0.03114799
[[1]]$tok
[1] "hello"
[[1]]$global_freq_ppb
[1] 211592.6
[[2]]
[[2]]$global_stdev_ppb
[1] 11561448
[[2]]$range
[1] 0.08870838
[[2]]$tok
[1] "world"
[[2]]$global_freq_ppb
[1] 1002043
我想将此列表转换为数据框,其中每个索引元素都是一列 . 自然(对我来说)要做的就是使用 do.call
:
> my.matrix<-do.call("rbind", my.list)
> my.matrix
global_stdev_ppb range tok global_freq_ppb
[1,] 24267673 0.03114799 "hello" 211592.6
[2,] 11561448 0.08870838 "world" 1002043
直截了当,但是当我尝试将此矩阵转换为数据框时,列仍然是列表元素,而不是向量:
> my.df<-as.data.frame(my.matrix, stringsAsFactors=FALSE)
> my.df[,1]
[[1]]
[1] 24267673
[[2]]
[1] 11561448
目前,为了正确地投射数据框,我使用 unlist
和 as.vector
迭代每一列,然后重建数据框:
new.list<-lapply(1:ncol(my.matrix), function(x) as.vector(unlist(my.matrix[,x])))
my.df<-as.data.frame(do.call(cbind, new.list), stringsAsFactors=FALSE)
然而,这看起来非常低效 . 有更好的方法吗?
7 回答
我想你想要:
另一种选择是:
但是这种简单的操作导致了列表的数据框:
对此的替代方案,沿着相同的路线,但现在结果与其他解决方案相同,是:
[ Edit: 包括了@Martin Morgan的两个解决方案的时间,这两个解决方案优于另一个返回向量数据帧的解决方案 . ]一个非常简单的问题的一些代表性时间:
我不能告诉你这在内存或速度方面是“最有效的”,但它在编码方面非常有效:
data.frame()的lapply()步骤将每个列表项转换为单行数据框,然后使用rbind()运行良好
虽然这个问题早已得到回答,但值得指出
data.table
包有rbindlist
可以很快完成这项任务:给我
这个
是一个函数,它返回一个提取x的第i个元素的函数 . 所以
得到一个名为(谢谢Map!)的矢量列表,可以将其作为数据框
对于速度来说,使用
unlist(lapply(...), use.names=FALSE)
通常会更快更一般的变体是
什么时候列表列表结构出现了?也许有一个更早的步骤,迭代可以被更多矢量化的东西取代?
dplyr包的
bind_rows
效率很高 .不确定它们在效率方面的排名,但根据列表的结构,有一些
tidyverse
选项 . 奖励是它们与不等长度列表很好地配合:您还可以混合矢量和数据帧: