web-dev-qa-db-fra.com

Construire une liste en boucle dans R - obtenir des noms d'élément corrects

J'ai une fonction qui contient une boucle sur deux listes et accumule des données calculées. Je voudrais renvoyer ces données sous forme de listes de listes, indexées par une valeur, mais je me trompe d'affectation.

Un exemple minimal de ce que j'essaie de faire, et où je vais mal serait:

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)
}

Si vous l'exécutez et regardez la sortie mybiglist, vous verrez que quelque chose va très mal dans la façon dont chaque élément est nommé.

Des idées sur la façon dont je pourrais réaliser ce que je veux réellement?

Merci

ps. Je sais que dans R il y a un sens dans lequel on a échoué si l'on doit recourir à des boucles, mais dans ce cas je me sens justifié ;-)

19
Hassantm

Cela fonctionne si vous n'utilisez pas la commande append:

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
35
Sven Hohenstein

Changement

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

à

mybiglist[[name]] <- tmp
5
seancarmody

Pour montrer qu'une boucle for explicite n'est pas requise

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)))

En général, si vous descendez le chemin de boucle for, il est préférable de préaffecter la liste au préalable. C'est plus efficace en mémoire.

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
}
3
mnel