Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Recursive Lists

Tags:

r

Consider the following code:

b <- list(u=5,v=12)
c <- list(w=13)
a <- list(b,c)

So a is really a list of lists. When I call a$b, or a$c, why is NULL returned? Likewise if I call a$u, a$v, or a$w, NULL is returned.

Also is there a difference between the following:

c(list(a=1,b=2,c=list(d=5,e=9))) 

and

c(list(a=1,b=2,c=list(d=5,e=9)), recursive=T)
like image 429
Damien Avatar asked Jan 02 '13 14:01

Damien


2 Answers

The $ indexing operator indexes the lists by name. If you want to get the first element from the unnamed list a, you need a[[1]].

You can make a function that automatically adds names if they are not specified, similar to the way data.frame works (this version is all-or-nothing -- if some arguments are named, it won't name the remaining, unnamed ones).

nlist <- function(...) {
    L <- list(...)
    if (!is.null(names(L))) return(L)
    n <- lapply(match.call(),deparse)[-1]
    setNames(L,n)
}

b <- c <- d <- 1

nlist(b,c,d)
nlist(d=b,b=c,c=d)

For your second question, the answer is "yes"; did you try it ???

L <- list(a=1,b=2,c=list(d=5,e=9))
str(c(L)) 
## List of 3
##  $ a: num 1
##  $ b: num 2
##  $ c:List of 2
##   ..$ d: num 5
##   ..$ e: num 9
str(c(L,recursive=TRUE))
##  Named num [1:4] 1 2 5 9
##  - attr(*, "names")= chr [1:4] "a" "b" "c.d" "c.e"

The first is a list including two numeric values and a list, the second has been flattened into a named numeric vector.

like image 127
Ben Bolker Avatar answered Nov 06 '22 03:11

Ben Bolker


For the first part of the question , we have in The R language definition document

The form using $ applies to recursive objects such as lists and pairlists. It allows only a literal character string or a symbol as the index. That is, the index is not computable: for cases where you need to evaluate an expression to find the index, use x[[expr]].

So you can change your a from a <- list(b,c) to a <- list(b=b,c=c)

 a$b =  a[['b']]   ## expression 
$u
[1] 5

$v
[1] 12

For the second part of the question , you can try for example to apply the $ operator, to see the difference.

> kk <- c(list(a=1,b=2,c=list(d=5,e=9)))              ## recursive objects
> hh <- c(list(a=1,b=2,c=list(d=5,e=9)), recursive=T) ## atomic objects
> kk$a
[1] 1
> hh$a
Error in hh$a : $ operator is invalid for atomic vectors

In reason we get a vector the from ?c for hh

If recursive = TRUE, the function recursively descends through lists (and pairlists) combining all their elements into a vector.

like image 29
agstudy Avatar answered Nov 06 '22 03:11

agstudy