Search code examples
rlistpopulate

How to properly populate a nested list and access its subelements in R


I just need to populate a nested list inside two for loops (for chain ALPHA and BETA, and for id), but I am getting a subscript out of bounds error.

This reproduces the problem:

mylist <- list()
mylist[['ALPHA']][[1]][['id1']]=46
mylist[['ALPHA']][[2]][['id1']]=28
mylist[['ALPHA']][[1]][['id2']]=87
mylist[['ALPHA']][[2]][['id2']]=12

However, if I do the following, I do not get the error, why is that?

mylist <- list()
mylist[['ALPHA']][['id1']][[1]]=46
mylist[['ALPHA']][['id1']][[2]]=28
mylist[['ALPHA']][['id2']][[1]]=87
mylist[['ALPHA']][['id2']][[2]]=12

I would rather prefer the structure above, since down the line I need the list with all ids for 1 and the list for all ids for 2.

These are easy to obtain with the structure above:

mylist1=mylist[['ALPHA']][[1]]
mylist2=mylist[['ALPHA']][[2]]

But how would I obtain such lists if the alternative structure is the only way to solve the error?

I tried this, but does not get me what I want (there is one more nested level):

sapply(mylist, "[", 2)

Any help? Thanks!


Solution

  • You can "prebuild" your list and then fill it.

    mylist <- list("ALPHA" = vector("list", 2))
    
    > mylist
    $ALPHA
    $ALPHA[[1]]
    NULL
    
    $ALPHA[[2]]
    NULL 
    

    Then your code works:

    > mylist[['ALPHA']][[1]][['id1']]=46
    > mylist[['ALPHA']][[2]][['id1']]=28
    > mylist[['ALPHA']][[1]][['id2']]=87
    > mylist[['ALPHA']][[2]][['id2']]=12
    
    > mylist
    
    $ALPHA
    $ALPHA[[1]]
    $ALPHA[[1]]$id1
    [1] 46
    
    $ALPHA[[1]]$id2
    [1] 87
    
    
    $ALPHA[[2]]
    $ALPHA[[2]]$id1
    [1] 28
    
    $ALPHA[[2]]$id2
    [1] 12
    

    As to why it works when starting from the "back"... Afaik when starting from [[2]] R is creating a list of length 2 so [[1]] has to be added at runtime. This is not the case for [[2]] when starting from [[1]], which causes the subscript out of bounds error. The second list entry needs to be added explicitly with a list() command.