Como eu usaria o purrr para executar uma simulação várias vezes com base em uma lista de cenários e uma função de simulação

Nov 24 2020

Quero usar tibble, df , uma lista de cenários, myscenarios e uma função de simulação, simu , para criar um resultado tibble com:

  1. 25 linhas de dados (cinco linhas para cada cenário)
  2. O quadro de dados de resultado deve incluir as seguintes colunas: x, n, v, cenário, resultado

Eu gostaria de conseguir isso usando a função purrr apropriada.

O reprex abaixo fornece a tabela, uma lista de cinco cenários e a função simu. A saída atual simplesmente utiliza a função simu contra a tabela df.

Lmap seria a função purrr correta para conseguir isso? Se sim, eu teria que usar lmap em conjunto com 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

Criado em 2020-11-23 pelo pacote reprex (v0.3.0)

Respostas

1 akrun Nov 24 2020 at 05:51

Podemos repetir o listde nomes com map, use assign ( :=) enquanto avaliando ( !!) para atribuir a saída aos nomes

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

-resultado

# 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

Se houver listfunções que correspondam aos elementos de 'myscenarios', podemos fazer um loop em ambos map2e, em seguida, aplicar a função (assumindo que eles têm os mesmos argumentos), no conjunto de dados, retornar uma única coluna com transmutee vincular ao conjunto de dados original

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