rnested-lists

How to directly select the same column from all nested lists within a list?


is it possible to directly select a column of all nested lists within a list?
My list is created using aggregate() with table():

AgN=aggregate(data,by=list(d$date),FUN=table,useNA="no")

AgN$x looks like:

$`0`

      1           2           3           9          11 
0.447204969 0.438509317 0.096894410 0.009937888 0.007453416 

$`1`

          1           2           4           8          11 
0.489974937 0.389724311 0.102756892 0.006265664 0.011278195 

…

$n

I want to get a vector of a specific column of each table, e.g. a vector containing the values of all columns named "1". I am still a R beginner, but even after searching and trying for a long time I found no nice solution. If I want to get the field of a list, I can simply index it with brackets, e.g. [i,j].
Online I found some examples for matrices, so I tried to do the same, at first only selecting one nested list’s column with AgN$x[1][1], but that is still selecting a whole list:

$0

     1           2           3           8          11 

0.447204969 0.438509317 0.096894410 0.009937888 0.007453416

My next try was AgN$x[[1]][1], and it was working:

  1 

0.447205

So I tried to to the same to select the value of each first column of all nested lists:

AgN$x[[1:length(AgN$x]][1]
Recursive indexing failed at level 2

Appearently the problem is that it is forbidden to select a range if you use a double brackets.

My last try was to use an for loop:

cduR=NULL 
for (i in 1:length(AgN$x)){
t=AgN$x[[i]]
cduR=c(cduR,as.vector(t["1"]))
}

Finally, so far that seems to working. But that way I had to build a loop each time when I want to select columns. Is there no direct way?

Thanks for your help.


Solution

  • Assuming you have something like the following:

    myList <- list(`0` = c(`1` = 10, `2` = 20, `3` = 30, `4` = 72),
                   `1` = c(`1` = 15, `2` = 9, `3` = 7))
    myList
    # $`0`
    #  1  2  3  4 
    # 10 20 30 72 
    # 
    # $`1`
    #  1  2  3 
    # 15  9  7 
    

    Use sapply() or lapply() to get into your list and extract whatever columns you want. Some examples.

    # As a list of one-column data.frames
    lapply(myList, `[`, 1)
    # $`0`
    #  1 
    # 10 
    # 
    # $`1`
    #  1 
    # 15 
    
    # As a list of vectors
    lapply(myList, `[[`, 1)
    # $`0`
    # [1] 10
    # 
    # $`1`
    # [1] 15
    
    # As a named vector
    sapply(myList, `[[`, 1)
    #  0  1 
    # 10 15 
    
    # As an unnamed vector
    unname(sapply(myList, `[[`, 1))
    # [1] 10 15
    

    Other variants of the syntax that also get you there include:

    ## Same output as above, different syntax
    lapply(myList, function(x) x[1])
    lapply(myList, function(x) x[[1]])
    sapply(myList, function(x) x[[1]])
    unname(sapply(myList, function(x) x[[1]]))
    

    A Nested List Example

    If you do have nested lists (lists within lists), try the following variants.

    # An example nested list
    myNestedList <- list(A = list(`0` = c(`1` = 10, `2` = 20, `3` = 30, `4` = 72),
                                  `1` = c(`1` = 15, `2` = 9, `3` = 7)),
                         B = list(`0` = c(A = 11, B = 12, C = 13),
                                  `1` = c(X = 14, Y = 15, Z = 16)))
    
    # Run the following and see what you come up with....
    lapply(unlist(myNestedList, recursive = FALSE), `[`, 1)
    lapply(unlist(myNestedList, recursive = FALSE), `[[`, 1)
    sapply(unlist(myNestedList, recursive = FALSE), `[[`, 1)
    rapply(myNestedList, f=`[[`, ...=1, how="unlist")
    

    Note that for lapply() and sapply() you need to use unlist(..., recursive = FALSE) while for rapply() (recursive apply), you refer to the list directly.