23

I have a function which contains a loop over two lists and builds up some calculated data. I would like to return these data as a lists of lists, indexed by some value, but I'm getting the assignment wrong.

A minimal example of what I'm trying to do, and where i'm going wrong would be:

mybiglist <- list()
for(i in 1:5){
    a <- runif(10)
    b <- rnorm(16)
    c <- rbinom(8, 5, i/10)
    name <- paste('item:',i,sep='')
    tmp <- list(uniform=a, normal=b, binomial=c)
    mybiglist[[name]] <- append(mybiglist, tmp)
}

If you run this and look at the output mybiglist, you will see that something is going very wrong in the way each item is being named.

Any ideas on how I might achieve what I actually want?

Thanks

ps. I know that in R there is a sense in which one has failed if one has to resort to loops, but in this case I do feel justified ;-)

Hassantm
  • 563
  • 1
  • 4
  • 14

3 Answers3

50

It works if you don't use the append command:

mybiglist <- list()
for(i in 1:5){
  a <- runif(10)
  b <- rnorm(16)
  c <- rbinom(8, 5, i/10)
  name <- paste('item:',i,sep='')
  tmp <- list(uniform=a, normal=b, binomial=c)
  mybiglist[[name]] <- tmp
}

# List of 5
# $ item:1:List of 3
# ..$ uniform : num [1:10] 0.737 0.987 0.577 0.814 0.452 ...
# ..$ normal  : num [1:16] -0.403 -0.104 2.147 0.32 1.713 ...
# ..$ binomial: num [1:8] 0 0 0 0 1 0 0 1
# $ item:2:List of 3
# ..$ uniform : num [1:10] 0.61 0.62 0.49 0.217 0.862 ...
# ..$ normal  : num [1:16] 0.945 -0.154 -0.5 -0.729 -0.547 ...
# ..$ binomial: num [1:8] 1 2 2 0 2 1 0 2
# $ item:3:List of 3
# ..$ uniform : num [1:10] 0.66 0.094 0.432 0.634 0.949 ...
# ..$ normal  : num [1:16] -0.607 0.274 -1.455 0.828 -0.73 ...
# ..$ binomial: num [1:8] 2 2 3 1 1 1 2 0
# $ item:4:List of 3
# ..$ uniform : num [1:10] 0.455 0.442 0.149 0.745 0.24 ...
# ..$ normal  : num [1:16] 0.0994 -0.5332 -0.8131 -1.1847 -0.8032 ...
# ..$ binomial: num [1:8] 2 3 1 1 2 2 2 1
# $ item:5:List of 3
# ..$ uniform : num [1:10] 0.816 0.279 0.583 0.179 0.321 ...
# ..$ normal  : num [1:16] -0.036 1.137 0.178 0.29 1.266 ...
# ..$ binomial: num [1:8] 3 4 3 4 4 2 2 3
Sven Hohenstein
  • 80,497
  • 17
  • 145
  • 168
  • Could you explain why within `mybiglist[[name]] <- tmp` "name" is in double brackets? – spops Dec 12 '17 at 23:11
  • 1
    @spops The double brackets are used for access of list elements. Single brackets return lists instead. – Sven Hohenstein Dec 13 '17 at 12:10
  • And is that why `append` fails when used with `[[]]`? Because you cannot append to the element, but you can append to a list? (I've been mucking around with all the ways to add items to lists and came across this post, and have been wondering) – spops Dec 13 '17 at 19:02
  • 1
    @spops `append` fails because the whole list is used to replace one of its elements. – Sven Hohenstein Dec 13 '17 at 19:26
  • @SvenHohenstein - Thank you for the answer. Is there a way I can find percentage difference between two `mybiglist` (`mybiglist_A` and `mybiglist_B`)? I can use `identical()` to get whether `mybiglist_A` is exactly same as `mybiglist_B` or not, but wondering if I can find percentage difference? – Chetan Arvind Patil Feb 14 '18 at 22:15
5

Change

mybiglist[[name]] <- append(mybiglist, tmp)

to

mybiglist[[name]] <- tmp
seancarmody
  • 6,182
  • 2
  • 34
  • 31
4

To show that an explicit for loop is not required

unif_norm  <- replicate(5, list(uniform = runif(10),
  normal = rnorm(16)), simplify=F)

binomials <- lapply(seq_len(5)/10, function(prob) {
 list(binomial =  rbinom(n = 5 ,size = 8, prob = prob))})

biglist <- setNames(mapply(c, unif_norm, binomials, SIMPLIFY = F), 
                     paste0('item:',seq_along(unif_norm)))

In general if you go down the for loop path it is better to preassign the list beforehand. This is more memory efficient.

mybiglist <- vector('list', 5)
names(mybiglist) <- paste0('item:', seq_along(mybiglist))
for(i in seq_along(mybiglist)){
    a <- runif(10)
    b <- rnorm(16)
    c <- rbinom(8, 5, i/10)

    tmp <- list(uniform=a, normal=b, binomial=c)
    mybiglist[[i]] <- tmp
}
mnel
  • 113,303
  • 27
  • 265
  • 254