Comment utiliser purrr pour exécuter une simulation plusieurs fois sur la base d'une liste de scénarios et d'une fonction de simulation

Nov 24 2020

Je veux utiliser tibble, df , une liste de scénarios, myscenarios et une fonction de simulation, simu , pour créer un résultat tibble avec:

  1. 25 lignes de données (cinq lignes pour chaque scénario)
  2. Le bloc de données de résultat doit inclure les colonnes suivantes: x, n, v, scénario, résultat

Je voudrais y parvenir en utilisant la fonction purrr appropriée.

Le reprex ci-dessous fournit le tibble, une liste de cinq scénarios et la fonction simu. La sortie courant utilise simplement la fonction simu contre le tibble df.

Est-ce que lmap serait la bonne fonction purrr pour y parvenir? Si oui, devrais-je utiliser lmap en conjonction avec mutate?

library(tidyverse)
df <- tibble(x= 1:5, 
             n= c("Jim","John","Jane","Jay","Jack"),
             v= 11:15)

myscenarios <- list("one", "two", "three", "four", "five")

simu <- function(x, v){
  x * v + sample(1:10, 1)
} 

result <- df %>% 
  mutate(result = simu(x, v))

result
#> # A tibble: 5 x 4
#>       x n         v result
#>   <int> <chr> <int>  <int>
#> 1     1 Jim      11     21
#> 2     2 John     12     34
#> 3     3 Jane     13     49
#> 4     4 Jay      14     66
#> 5     5 Jack     15     85

Créé le 2020-11-23 par le package reprex (v0.3.0)

Réponses

1 akrun Nov 24 2020 at 05:51

Nous pouvons boucler sur les listnoms avec map, utiliser assign ( :=) tout en évaluant ( !!) pour affecter la sortie aux noms

library(dplyr)
library(purrr)
map_dfc(myscenarios, ~ df %>% 
                   transmute(!! .x := simu(x, v))) %>%
      bind_cols(df, .)

-production

# A tibble: 5 x 8
#      x n         v   one   two three  four  five
#  <int> <chr> <int> <int> <int> <int> <int> <int>
#1     1 Jim      11    16    17    20    13    15
#2     2 John     12    29    30    33    26    28
#3     3 Jane     13    44    45    48    41    43
#4     4 Jay      14    61    62    65    58    60
#5     5 Jack     15    80    81    84    77    79

S'il y a listdes fonctions qui correspondent aux éléments de 'myscenarios', nous pouvons boucler les deux avec map2puis appliquer la fonction (en supposant qu'elles ont les mêmes arguments), sur l'ensemble de données, renvoyer une seule colonne avec transmuteet lier avec l'ensemble de données d'origine

lstfn <- list(simu, simu, simu, simu, simu)
map2_dfc(myscenarios, lstfn, ~ df %>%
         transmute(!! .x := .y(x, v))) %>%
     bind_cols(df, .)