简体   繁体   中英

How to display a list of lists in a nice way

I have a list of lists, such as below.

Each list (eg list1, list2, list3) has two attributes: Variable and Time

list1 <- list(c("Color", "Price"), "Quarter")
list2 <- list(c("Price"), "Month")
list3 <- list(c("Color"), "Month")
total <- list(list1, list2, list3)

when we print total , we'll see:

[[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"

How can I turn it into a data frame such as this one?

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))

This isn't just a nested- list problem, it's a nested problem. If I'm interpretting things correctly, the fact that Color and Price are in one list and Quarter is in another is meaningful. So really, you should be looking at how to turn the first element of each list into a data.frame , repeat for all other elements, then join the results. (This is where @divibisan's and @camille's suggestions come into play ... reduce the problem, use the duplicates' code, then combine.)

(The fact that I believe you will never have more than two elems in each list is not strictly a factor. Below is a general way of handling 1-or-more, not just "always 2".)

Your data:

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"

What we need to do is break this down by element-of-each-list. (I'm assuming that there will be symmetry here.) Let's start by just working on the first elem of each:

total1 <- lapply(total, `[[`, 1)
str(total1)
# List of 3
#  $ : chr [1:2] "Color" "Price"
#  $ : chr "Price"
#  $ : chr "Color"

In order to use the suggestions from the dupes, we need to know how much to pad them. That is, they need to be the same length.

( maxlen <- max(sapply(total1, function(l) length(unlist(l)))) )
# [1] 2

Now we pad them:

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

(You can start to see the structure break out here.) The dupes suggested cbind ing them, but you want to rbind them:

do.call(rbind, total1)
#      [,1]    [,2]   
# [1,] "Color" "Price"
# [2,] "Price" NA     
# [3,] "Color" NA     

Now this is a matrix , not a data.frame , but it's a start. Let's work with naming at the end. Let's write a function to do what we just did, and then we'll use it on each level of total .

In order to do this, though, we need to modify total , so that the new first element has all first elements, new second has all seconds, etc.

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"  

So this last point is pretty much what you need, though as a matrix . From here, it's easy enough to name things:

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM