Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

building nested lists in R

Tags:

loops

list

r

nested

I have written a function that it's output is a list. I want to put my function into a loop and I'd like to store output of each iteration (which is of course a list) into a bigger list. In other words, each element of this BIG list is also a list. c() does not do what I want. Is there any way to do that?

To understand better what I'm asking, consider the example below:

iter1 <- list(item1 = 1, item2 = "a")
iter2 <- list(item1 = 1, item2 = "b")
All <- list(iter1 = iter1, iter2 = iter2)

I want to be able to do something similar to the code above but in a loop. How can I do that?

Thanks for your help,

like image 373
Sam Avatar asked May 17 '13 05:05

Sam


People also ask

How can we create nested lists?

The proper way to make HTML nested list is with the nested <ul> as a child of the <li> to which it belongs. The nested list should be inside of the <li> element of the list in which it is nested.

What is nested list with example?

A nested list is a list that appears as an element in another list. In this list, the element with index 3 is a nested list. If we print( nested[3] ), we get [10, 20] .

How do I create a list of objects in R?

How to Create Lists in R? We can use the list() function to create a list. Another way to create a list is to use the c() function. The c() function coerces elements into the same type, so, if there is a list amongst the elements, then all elements are turned into components of a list.

How do you define a nested list?

A nested list is simply a list that occurs as an element of another list (which may of course itself be an element of another list, etc.). Common reasons nested lists arise are: They're matrices (a list of rows, where each row is itself a list, or a list of columns where each column is itself a list).


1 Answers

There's another way to assign to a list, using my_list[[name or number]] <-. If you really want to do that in a loop, just looping over things with names like iter1, iter2, ...

A <- list()
n_iter <- 2
for (i in 1:n_iter){
    iname <- paste("iter",i,sep="")
    A[[iname]] <- get(iname)
}

As @mnel pointed out, dynamically growing a list is inefficient. The alternative is, I think, to use lapply:

n_iter <- 2
inames <- paste("iter",1:n_iter,sep="")
names(inames) <- inames
A <- lapply(inames,get)

This can also be done with a data frame, which would be a better format if your sublists always have two elements, each having a consistent class (item1 being numeric and item 2 being character).

n_iter <- 2
DF <- data.frame(item1=rep(0,n_iter),item2=rep("",n_iter),stringsAsFactors=FALSE)
for (i in 1:n_iter){
     iname <- paste("iter",i,sep="")
     DF[i,] <- get(iname)
     rownames(DF)[i] <- iname
}

#       item1 item2
# iter1     1     a
# iter2     1     b

However, that's a pretty ugly way of doing things; things get messy pretty quickly when using get. With your data structure, maybe you want to create iter1 and iter2 in a loop and immediately embed them into the parent list or data frame?

n_iter = 10
DF <- data.frame(item1 = rep(0,n_iter), item2 = rep("",n_iter))
for (i in 1:n_iter){
    ... do stuff to make anum and achar ...
    DF[i,"item1"] <- anum
    DF[i,"item2"] <- achar
}

Where anum and achar are the values of item1 and item2 you want to store from that iteration. Elsewhere on SO, they say that there is an alternative using the data.table package that is almost 10x as fast/efficient as this sort of data-frame assignment.

Oh, one last idea: if you want to put them in a list first, you can easily convert to a data frame later with

DF <- do.call(rbind.data.frame,A)
like image 161
Frank Avatar answered Oct 06 '22 11:10

Frank