遇到问题。 我需要将一个不规则的列表列表转换为宽格式的data.frame(即我需要相同数量的行),我只是无法弄清楚如何做到这一点。 列表看起来像这样:
[[1]]
[1] 14
[[2]]
[1] 26
[[3]]
[1] 20 21 22 23
[[4]]
[1] 21 22
[[5]]
[1] 25
[[6]]
[1] 17 21 23
我尝试过使用for循环和/或sapply的各种方法,但没有任何作用。不同长度的列表元素排除了我所做的任何尝试。在我看来,必须有一种相当直接的方法来做到这一点。一定不是吗?有人可以建议吗?
答案 0 :(得分:6)
这是一个lapply
/ mapply
示例......
# Data
set.seed(1)
ll <- replicate( 4 , runif( sample(4,1) ) )
str(ll)
#List of 4
# $ : num [1:2] 0.372 0.573
# $ : num [1:4] 0.202 0.898 0.945 0.661
# $ : num [1:3] 0.0618 0.206 0.1766
# $ : num [1:3] 0.384 0.77 0.498
# Find length of each list element
len <- sapply(ll,length)
# Longest gives number of rows
n <- max( len )
# Number of NAs to fill for column shorter than longest
len <- n - len
# Output
mapply( function(x,y) c( x , rep( NA , y ) ) , ll , len )
# [,1] [,2] [,3] [,4]
#[1,] 0.3721239 0.2016819 0.06178627 0.3841037
#[2,] 0.5728534 0.8983897 0.20597457 0.7698414
#[3,] NA 0.9446753 0.17655675 0.4976992
#[4,] NA 0.6607978 NA NA
注意,输出是一个矩阵,因此您需要使用data.frame()
包装输出。
data.frame( t( mapply( function(x,y) c( x , rep( NA , y ) ) , ll , len ) ) )
# X1 X2 X3 X4
#1 0.37212390 0.5728534 NA NA
#2 0.20168193 0.8983897 0.9446753 0.6607978
#3 0.06178627 0.2059746 0.1765568 NA
#4 0.38410372 0.7698414 0.4976992 NA
答案 1 :(得分:1)
另一种方法:
### set all lengths to maximum length (here=4)
### this will 'fill in' with NAs where needed
n <- 4
for (i in 1:length(ll)){
length(ll[[i]]) <- n
}
matrix(unlist(ll), ncol=n)
### @Aruns approach is similar to the above;
### it uses the fact that subsetting by indices
### which do not exist results in NAs e.g.
> (ll[[1]][1:n])
[1] 0.3721239 0.5728534 NA NA
### (using original `ll`)
d1 <- as.data.frame(lapply(ll, "[", 1:n))
colnames(d1) <- seq(4)
d1
### this is more roundabout
library(plyr)
### `ldply` takes list; returns data.frame
### default function applied is `rbind.fill`, which works here
### however `t` coerces this back to a matrix
### (using `ll` as modified by `for` loop in first answer)
t(ldply(ll))
[,1] [,2] [,3] [,4]
1 0.3721239 0.2016819 0.06178627 0.3841037
2 0.5728534 0.8983897 0.20597457 0.7698414
3 NA 0.9446753 0.17655675 0.4976992
4 NA 0.6607978 NA NA
答案 2 :(得分:1)
一种简单的方法是首先将数据转换为“长”形式(例如,使用“融化”),添加“时间”变量,然后使用dcast
或reshape
将数据恢复为新的“宽”形式。
这些示例使用@ Simon的答案中的ll
:
这是一种“reshape2”方法:
library(reshape2)
ll2 <- melt(ll)
ll2$time <- ave(ll2$L1, ll2$L1, FUN = seq_along)
dcast(ll2, L1 ~ time, value.var="value")
# L1 1 2 3 4
# 1 1 0.37212390 0.5728534 NA NA
# 2 2 0.20168193 0.8983897 0.9446753 0.6607978
# 3 3 0.06178627 0.2059746 0.1765568 NA
# 4 4 0.38410372 0.7698414 0.4976992 NA
## Or, for the other orientation:
dcast(ll2, time ~ L1, value.var="value")
如果您使用的是软件包的至少1.8.11版本,也可以使用“data.table”软件包
library(data.table)
library(reshape2)
packageVersion("data.table") ## Need at least V 1.8.11
# [1] ‘1.8.11’
DT <- data.table(ll)
DTL <- DT[, unlist(ll), by = 1:nrow(DT)]
DTL[, time := sequence(.N), by = nrow]
dcast.data.table(DTL, nrow ~ time, value.var="V1")
# nrow 1 2 3 4
# 1: 1 0.37212390 0.5728534 NA NA
# 2: 2 0.20168193 0.8983897 0.9446753 0.6607978
# 3: 3 0.06178627 0.2059746 0.1765568 NA
# 4: 4 0.38410372 0.7698414 0.4976992 NA
## Or, for the other orientation
dcast.data.table(DTL, time ~ nrow, value.var="V1")
这两个方面都有额外的好处,可以方便地将NA
替换为您想要使用的任何其他内容。