有一个这样的列表,从1开始。
[[7158]]
[1] 81 72
[[7159]]
[1] 81 69
[[7160]]
[1] 81 79
[[7161]]
[1] 81 84
这需要更改为数据框,其中每个元素中的第一个数字在一个数据框列中对齐,每个元素中的第二个数字放在数据框的第二列中。所以它应该像这样结束
> data.frame("col1" = c(81, 81, 81, 81), "col2" = c(72, 69, 79, 84))
col1 col2
1 81 72
2 81 69
3 81 79
4 81 84
我尝试过do.call(rbind.data.frame, my_list)
,但它似乎将数字放在大量的列中,而不是将其强制转换为所需的两列。使用循环执行此操作将非常简单,但R方式是什么?感谢。
答案 0 :(得分:8)
只需设置名称:
mylist <- list(c(81,72), c(81,63), c(81,79))
setNames(do.call(rbind.data.frame, mylist), c("col1", "col2"))
# col1 col2
#1 81 72
#2 81 63
#3 81 79
与其他一些解决方案相比,这也适用于混合数据类型:
mylist <- list(list("a", 72), list("b", 63), list("c", 79))
res <- setNames(do.call(rbind.data.frame, mylist), c("col1", "col2"))
str(res)
#'data.frame': 3 obs. of 2 variables:
# $ col1: Factor w/ 3 levels "a","b","c": 1 2 3
# $ col2: num 72 63 79
答案 1 :(得分:4)
您可以尝试以下任何一项:
do.call(rbind, my_list)
t(simplify2array(my_list))
library(stringi)
stri_list2matrix(my_list, byrow = TRUE)
以上所有内容都会生成两列matrix
,其中包含您描述的数据,因此您可以使用as.data.frame
获取data.frame
。
上述替代方案的时间安排以及@Roland的建议can be found at this Gist。总结一下,&#34; stringi&#34;方法将是迄今为止提出的最快的选择。如果我没有弄错,{&1;}在&#34; data.table&#34;也应该支持转换向量列表 - 但我没有在GitHub上用开发版本进行测试来验证,所以我没有在这里包含该选项。
答案 2 :(得分:1)
您可以尝试使用
Reduce( rbind, lapply(t1, t) )
答案 3 :(得分:1)
另一个想法:
mylist = list(c(81, 72), c(81, 69), c(81, 79), c(81, 84))
f4 = function(x)
{
tlist = lapply(seq_along(x[[1]]),
function(i) unlist(lapply(x, "[[", i)))
structure(tlist, class = "data.frame",
row.names = .set_row_names(as.integer(length(tlist[[1]]))),
names = paste("col", seq_along(tlist), sep = ""))
}
f4(mylist)
# col1 col2
#1 81 72
#2 81 69
#3 81 79
#4 81 84
与其他选项的基准:
library(stringi)
f1 = function(x)
setNames(as.data.frame(type.convert(stri_list2matrix(x, byrow = TRUE))),
paste("col", seq_along(x[[1]]), sep = ""))
f2 = function(x)
setNames(do.call(rbind.data.frame, x),
paste("col", seq_along(x[[1]]), sep = ""))
f3 = function(x)
setNames(as.data.frame(Reduce(rbind, lapply(x, t))),
paste("col", seq_along(x[[1]]), sep = ""))
myls = replicate(1e3, sample(1e2), simplify = F)
identical(f1(myls), f2(myls))
#[1] TRUE
identical(f1(myls), f3(myls))
#[1] TRUE
identical(f1(myls), f4(myls))
#[1] TRUE
microbenchmark::microbenchmark(f1(myls), f2(myls), f3(myls), f4(myls), times = 10)
#Unit: milliseconds
# expr min lq median uq max neval
# f1(myls) 57.66834 58.46979 59.39131 61.43861 102.27333 10
# f2(myls) 393.81459 404.29019 418.03128 422.87740 494.79857 10
# f3(myls) 288.39078 299.51680 305.21727 314.75482 374.48683 10
# f4(myls) 52.54991 53.26575 55.34472 59.25559 75.19658 10
答案 4 :(得分:1)
在current development version of data.table, v1.9.5中,有一个新功能transpose()
,用于转置列表。我们可以将其与setDT()
一起使用,如下所示。
require(data.table) # v1.9.5+
ll = lapply(1:1e6, function(x) sample(100, 2))
dt = setDT(transpose(ll))
system.time(setDT(transpose(ll))
# user system elapsed
# 0.073 0.000 0.073
如果你想要一个data.frame,那么你可以在这个结果上使用setDF()
(它将data.table转换为data.frame而不需要任何副本)。