我有一个嵌套的数据列表。它的长度是132,每一项是一个长度为20的列表。是否有一种快速的方法可以将这种结构转换为具有132行和20列数据的数据帧?
下面是一些示例数据:
l <- replicate(
132,
as.list(sample(letters, 20)),
simplify = FALSE
)
我有一个嵌套的数据列表。它的长度是132,每一项是一个长度为20的列表。是否有一种快速的方法可以将这种结构转换为具有132行和20列数据的数据帧?
下面是一些示例数据:
l <- replicate(
132,
as.list(sample(letters, 20)),
simplify = FALSE
)
当前回答
Reshape2产生与上面的plyr示例相同的输出:
library(reshape2)
l <- list(a = list(var.1 = 1, var.2 = 2, var.3 = 3)
, b = list(var.1 = 4, var.2 = 5, var.3 = 6)
, c = list(var.1 = 7, var.2 = 8, var.3 = 9)
, d = list(var.1 = 10, var.2 = 11, var.3 = 12)
)
l <- melt(l)
dcast(l, L1 ~ L2)
收益率:
L1 var.1 var.2 var.3
1 a 1 2 3
2 b 4 5 6
3 c 7 8 9
4 d 10 11 12
如果你几乎没有像素,你可以在一行w/ recast()中完成这一切。
其他回答
Reshape2产生与上面的plyr示例相同的输出:
library(reshape2)
l <- list(a = list(var.1 = 1, var.2 = 2, var.3 = 3)
, b = list(var.1 = 4, var.2 = 5, var.3 = 6)
, c = list(var.1 = 7, var.2 = 8, var.3 = 9)
, d = list(var.1 = 10, var.2 = 11, var.3 = 12)
)
l <- melt(l)
dcast(l, L1 ~ L2)
收益率:
L1 var.1 var.2 var.3
1 a 1 2 3
2 b 4 5 6
3 c 7 8 9
4 d 10 11 12
如果你几乎没有像素,你可以在一行w/ recast()中完成这一切。
包数据。Table中有rbindlist函数,它是do的一个超快速实现。调用(rbind列表(…))。
它可以接受一个列表的列表,data。frame或data。表作为输入。
library(data.table)
ll <- list(a = list(var.1 = 1, var.2 = 2, var.3 = 3)
, b = list(var.1 = 4, var.2 = 5, var.3 = 6)
, c = list(var.1 = 7, var.2 = 8, var.3 = 9)
, d = list(var.1 = 10, var.2 = 11, var.3 = 12)
)
DT <- rbindlist(ll)
这会返回一个数据。表继承自data.frame。
如果你真的想转换回data。frame使用as。data。frame(DT)
我发现的每个解决方案似乎只适用于列表中的每个对象都具有相同的长度。当列表中对象的长度不相等时,我需要将列表转换为data.frame。下面是我提出的基于R的解决方案。毫无疑问,这是非常低效的,但它似乎确实有效。
x1 <- c(2, 13)
x2 <- c(2, 4, 6, 9, 11, 13)
x3 <- c(1, 1, 2, 3, 3, 4, 5, 5, 6, 7, 7, 8, 9, 9, 10, 11, 11, 12, 13, 13)
my.results <- list(x1, x2, x3)
# identify length of each list
my.lengths <- unlist(lapply(my.results, function (x) { length(unlist(x))}))
my.lengths
#[1] 2 6 20
# create a vector of values in all lists
my.values <- as.numeric(unlist(c(do.call(rbind, lapply(my.results, as.data.frame)))))
my.values
#[1] 2 13 2 4 6 9 11 13 1 1 2 3 3 4 5 5 6 7 7 8 9 9 10 11 11 12 13 13
my.matrix <- matrix(NA, nrow = max(my.lengths), ncol = length(my.lengths))
my.cumsum <- cumsum(my.lengths)
mm <- 1
for(i in 1:length(my.lengths)) {
my.matrix[1:my.lengths[i],i] <- my.values[mm:my.cumsum[i]]
mm <- my.cumsum[i]+1
}
my.df <- as.data.frame(my.matrix)
my.df
# V1 V2 V3
#1 2 2 1
#2 13 4 1
#3 NA 6 2
#4 NA 9 3
#5 NA 11 3
#6 NA 13 4
#7 NA NA 5
#8 NA NA 5
#9 NA NA 6
#10 NA NA 7
#11 NA NA 7
#12 NA NA 8
#13 NA NA 9
#14 NA NA 9
#15 NA NA 10
#16 NA NA 11
#17 NA NA 11
#18 NA NA 12
#19 NA NA 13
#20 NA NA 13
一个简短的(但可能不是最快的)方法是使用基底r,因为数据帧只是一个长度相等的向量的列表。因此,你的输入列表和一个30 x 132 data.frame之间的转换将是:
df <- data.frame(l)
从这里我们可以将其转置为132 x 30的矩阵,并将其转换回数据帧:
new_df <- data.frame(t(df))
一句话:
new_df <- data.frame(t(data.frame(l)))
行名看起来很讨厌,但是您总是可以用
行名称(new_df) <- 1:nrow(new_df)
l <- replicate(10,list(sample(letters, 20)))
a <-lapply(l[1:10],data.frame)
do.call("cbind", a)