web-dev-qa-db-fra.com

purrr map équivalent de nested for loop

Quel est l'équivalent purrr :: map de:

for (i in 1:4) {
  for (j in 1:6) {
    print(paste(i, j, sep = "-"))
  }
}

OR

lapply(1:4, function(i) 
  lapply(1:6, function(j) 
    print(paste(i, j, sep = "-"))))

Conceptuellement, ce que je ne comprends pas, c'est comment faire référence à la boucle externe dans la fonction de carte intérieure.

map(1:4, ~ map(1:6, ~ print(paste(.x, ????, sep = "-")))
17
merov

Comme le souligne @ r2evans, le .x de votre premier appel est masqué. mais vous pouvez créer une fonction lambda qui prend 2 paramètres .x et .y, et attribuez le précédent .x vers le nouveau .y à travers le ... argument.

Je vais utiliser walk plutôt que map car dans ce cas, vous n'êtes intéressé que par les effets secondaires (impression)

walk(1:4,~ walk(1:6, ~ print(paste(.x, .y, sep = "-")),.y=.x))

Une autre option consiste à utiliser expand.grid pour disposer les combinaisons, puis répéter celles avec pwalk (ou pmap dans d'autres circonstances)

purrr::pwalk(expand.grid(1:4,1:6),~print(paste(.x, .y, sep = "-")))

Sortie dans les deux cas:

[1] "1-1"
[1] "2-1"
[1] "3-1"
[1] "4-1"
[1] "5-1"
[1] "6-1"
[1] "1-2"
[1] "2-2"
[1] "3-2"
[1] "4-2"
[1] "5-2"
[1] "6-2"
[1] "1-3"
[1] "2-3"
[1] "3-3"
[1] "4-3"
[1] "5-3"
[1] "6-3"
[1] "1-4"
[1] "2-4"
[1] "3-4"
[1] "4-4"
[1] "5-4"
[1] "6-4"
14
Moody_Mudskipper

L'utilisation de formules de fonction (~) est un peu limité lorsque vous essayez d'imbriquer comme ceci, car il est parfaitement difficile de savoir à quel niveau de map vous essayez de faire référence. (Eh bien, ce n'est pas correct. Il est parfaitement clair pour moi qu'il fait référence à l'envers , et comme ils utilisent tous les deux la même nomenclature, les variables externes sont masqués par les variables internes.)

Je pense que votre meilleur moyen de le contourner est de ne pas utiliser la méthode de formule, plutôt d'utiliser des fonctions immédiates/anonymes (ou prédéfinies):

library(purrr)
str(map(1:2, function(x) map(1:3, function(y) paste(x, y, sep = "-"))))
# List of 2
#  $ :List of 3
#   ..$ : chr "1-1"
#   ..$ : chr "1-2"
#   ..$ : chr "1-3"
#  $ :List of 3
#   ..$ : chr "2-1"
#   ..$ : chr "2-2"
#   ..$ : chr "2-3"
21
r2evans

Je passe juste par là maintenant.

walk(1:4,~ walk(1:6, ~ print(paste(.x, .y, sep = "-")),.y=.x)) 
[1] "1-1"
[1] "2-1"
[1] "3-1"
[1] "4-1"
[1] "5-1"
[1] "6-1"
[1] "1-2"

et

purrr::pwalk(expand.grid(1:4,1:6),~print(paste(.x, .y, sep = "-")))
[1] "1-1"
[1] "2-1"
[1] "3-1"
[1] "4-1"
[1] "1-2"

mais pour correspondre exactement à vos boucles imbriquées, cela a fonctionné et cela fonctionne.

for (i in 1:4) {
  for (j in 1:6) {
    print(paste(i, j, sep = "-"))
  }
}
[1] "1-1"
[1] "1-2"
[1] "1-3"
[1] "1-4"
[1] "1-5"
[1] "1-6"
[1] "2-1"

purrr::pwalk(expand.grid(1:6,1:4),~print(paste(.y, .x, sep = "-")))
[1] "1-1"
[1] "1-2"
[1] "1-3"
[1] "1-4"
[1] "1-5"
[1] "1-6"
[1] "2-1"

#or even a map of this
walk(1:4,~ walk(1:6, ~ print(paste(.y, .x, sep = "-")),.y=.x))

Je n'ai pas encore compris pourquoi le .y=.x est cependant à la fin.

1
Shadowhawk