[英]How to display a list of lists in a nice way
我有一个列表列表,如下所示。
每个列表(例如list1,list2,list3)都有两个属性:Variable和Time
list1 <- list(c("Color", "Price"), "Quarter")
list2 <- list(c("Price"), "Month")
list3 <- list(c("Color"), "Month")
total <- list(list1, list2, list3)
当我们打印total
,我们将看到:
[[1]]
[[1]][[1]]
[1] "Color" "Price"
[[1]][[2]]
[1] "Quarter"
[[2]]
[[2]][[1]]
[1] "Price"
[[2]][[2]]
[1] "Month"
[[3]]
[[3]][[1]]
[1] "Color"
[[3]][[2]]
[1] "Month"
如何将其转换为这样的数据帧?
EDIT: I am able to accomplish it using this code. Any better suggestion is appreciated!
num <- length(total)
max <- 0
for(i in 1:num) {
if(length(total[[i]][1]) > max) {
max <- length(total[[i]])
}
}
for(i in 1:num) {
length(total[[i]][[1]]) <- max
for(j in 1:max) {
if(is.null(total[[i]][[1]][[j]])) {
total[[i]][[1]][[j]] <- " "
}
}
}
df <- data.frame(matrix(unlist(total), nrow=num, byrow=T))
这不仅是一个嵌套list
问题,还是一个嵌套问题。 如果我正确地解释了事情,那么颜色和价格在一个列表中,而四分之一在另一个列表中这一事实是有意义的。 因此,实际上,您应该研究如何将每个列表的第一个元素转换为data.frame
,对所有其他元素重复此操作,然后加入结果。 (这是@divibisan和@camille的建议开始起作用的地方...减少问题,使用重复项的代码,然后合并。)
(事实上,我相信您在每个列表中都不会有两个以上的元素严格来说并不是一个因素。以下是处理1个或多个对象的一般方法,而不仅仅是“总是2个”。)
您的数据:
str(total)
# List of 3
# $ :List of 2
# ..$ : chr [1:2] "Color" "Price"
# ..$ : chr "Quarter"
# $ :List of 2
# ..$ : chr "Price"
# ..$ : chr "Month"
# $ :List of 2
# ..$ : chr "Color"
# ..$ : chr "Month"
我们需要做的是通过每个元素列表来分解它。 (我假设这里是对称的。)让我们从处理每个元素的第一个元素开始:
total1 <- lapply(total, `[[`, 1)
str(total1)
# List of 3
# $ : chr [1:2] "Color" "Price"
# $ : chr "Price"
# $ : chr "Color"
为了使用双轨骗局的建议,我们需要知道填充多少。 也就是说,它们必须具有相同的长度。
( maxlen <- max(sapply(total1, function(l) length(unlist(l)))) )
# [1] 2
现在我们填充它们:
total1 <- lapply(total1, function(l) { length(l) <- maxlen; l; })
str(total1)
# List of 3
# $ : chr [1:2] "Color" "Price"
# $ : chr [1:2] "Price" NA
# $ : chr [1:2] "Color" NA
(您可以在这里开始看到该结构的破裂。) cbind
建议cbind
它们cbind
,但是您想rbind
它们:
do.call(rbind, total1)
# [,1] [,2]
# [1,] "Color" "Price"
# [2,] "Price" NA
# [3,] "Color" NA
现在这是一个matrix
,而不是data.frame
,但这是一个开始。 最后,让我们开始命名。 让我们编写一个函数来完成我们刚刚做的事情,然后在total
每个级别上使用它。
为了做到这一点,我们需要修改total
,以便新的第一个元素具有所有第一个元素,新的第二个元素具有所有秒,依此类推。
newtotal <- lapply(seq_len(max(sapply(total, length))), function(i) lapply(total, `[[`, i))
str(newtotal)
# List of 2
# $ :List of 3
# ..$ : chr [1:2] "Color" "Price"
# ..$ : chr "Price"
# ..$ : chr "Color"
# $ :List of 3
# ..$ : chr "Quarter"
# ..$ : chr "Month"
# ..$ : chr "Month"
m <- do.call(cbind, lapply(newtotal, func))
m
# [,1] [,2] [,3]
# [1,] "Color" "Price" "Quarter"
# [2,] "Price" NA "Month"
# [3,] "Color" NA "Month"
因此,尽管作为matrix
,这最后一点几乎是您所需要的。 从这里开始,命名很容易:
m <- do.call(cbind, lapply(newtotal, func))
colnames(m) <- c(paste0("Var", seq_len(ncol(m)-1L)), "Time")
df <- as.data.frame(m)
df$List <- paste0('List', seq_len(nrow(df)))
df
# Var1 Var2 Time List
# 1 Color Price Quarter List1
# 2 Price <NA> Month List2
# 3 Color <NA> Month List3
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.