Comment ajouter un troisième élément de liste dynamique à mon instruction pmap_dfc
J'ai le code de travail suivant qui utilise deux listes pour produire une sortie de simulation:
strategy_list <- list("s_Win","s_WinH1", "s_WinH2", "s_WinH1F1", "s_WinH2F2", "s_WinDerEx")
function_list <- list(s_win, s_winH1, s_winH2, s_winH1F1, s_winH2F2, s_winDerEx)
l <- list(strategy_list, function_list)
simulation <- pmap_dfc(l, ~ df %>%
transmute(!! .x := .y(entries, skill, field, win_payoff, wager_amt, Winner, exacta_payoff))) %>%
bind_cols(df, .)
Maintenant, je voudrais exécuter la simulation à plusieurs niveaux de compétence différents, j'ai donc ajouté une boucle et j'ai essayé de remplacer l'entrée de compétence par i de la boucle pour créer plusieurs variantes de la simulation:
for (i in seq(from = 0.15, to=0.30, by=0.05)){
skill_list <- list(i, i, i, i, i, i)
strategy_list <- list("s_Win","s_WinH1", "s_WinH2", "s_WinH1F1", "s_WinH2F2", "s_WinDerEx")
function_list <- list(s_win, s_winH1, s_winH2, s_winH1F1, s_winH2F2, s_winDerEx)
l <- list(skill_list, strategy_list, function_list)
simulation <- pmap_dfc(l, ~ df %>%
transmute(!! .w !! .x := .y(entries, i, field, win_payoff, wager_amt, Winner, exacta_payoff))) %>%
bind_cols(df, .)
}
Malheureusement, cela produit une erreur. J'ai essayé plusieurs variantes, mais je n'arrive pas à faire fonctionner le code.
EDIT: Basé sur le post d'Atem ci-dessous, j'ai mis à jour mon code comme suit:
for (i in seq(from = 0.15, to=0.30, by=0.05)){
strategy_list <- list("s_Win","s_WinH1", "s_WinH2", "s_WinH1F1", "s_WinH2F2", "s_WinDerEx") %>% stringr::str_c(i)
function_list <- list(s_win, s_winH1, s_winH2, s_winH1F1, s_winH2F2, s_winDerEx)
skill_list <- list(i, i, i, i, i, i)
l <- list(strategy_list, function_list, skill_list)
simulation <- pmap_dfc(l, ~ df %>%
transmute(!! ..1 := ..2 (entries, ..3, field, win_payoff, wager_amt, Winner, exacta_payoff))) %>%
bind_cols(df, .) %>%
Malheureusement, cela produit toujours une erreur. Le problème semble être avec ..2 car il ne reçoit pas la même coloration syntaxique que ..1 et ..3.
EDIT 2: Pour rendre cela un peu plus simple, j'ai rassemblé une version simplifiée de ma question et inclus un reprex. Simulation1 avec deux listes fonctionne très bien. Simulation2 avec trois listes et la boucle échoue avec le message d'erreur: impossible de trouver la fonction "..2".
``` r
library(tidyverse)
z <- 5
df <- tibble(x=1:10, y=1:10)
s_win <- function(x,y,z){
a <-rnorm(x) + x + y + 1 +z
a
}
s_win1 <- function(x,y,z){
b <- rnorm(x) + x + y + 2 + z
b
}
s_win2 <- function(x,y,z){
c <- rnorm(x) + x + y + 3 +z
c
}
# Simulation1 with two list works.
strategy_list <- list("s_Win","s_Win1", "s_Win2")
function_list <- list(s_win, s_win1, s_win2)
l <- list(strategy_list, function_list)
simulation1 <- pmap_dfc(l, ~ df %>%
transmute(!! .x := .y (x, y, z))) %>%
bind_cols(df, .) %>%
pivot_longer(
cols = starts_with("s_"),
names_to = "Strategy",
names_prefix = "s_",
values_to = "Value",
values_drop_na = TRUE
)
View(simulation1)
# Simulation 2 with thre list does not work. Error message = could not find function "..2"
for (i in seq(from = 5, to=20, by=5)){
strategy_list <- list("s_Win","s_Win1", "s_Win2") %>% stringr::str_c(i)
function_list <- list(s_win, s_win1, s_win2)
skill_list <- list(i, i, i)
l <- list(strategy_list, function_list, skill_list)
simulation2 <- pmap_dfc(l, ~ df %>%
transmute(!! ..1 := ..2 (x, y, ..3))) %>%
bind_cols(df, .) %>%
pivot_longer(
cols = starts_with("s_"),
names_to = "Strategy",
names_prefix = "s_",
values_to = "Value",
values_drop_na = TRUE
)
}
#> Error: Problem with `mutate()` input `s_Win5`.
#> x could not find function "..2"
#> i Input `s_Win5` is `..2(x, y, ..3)`.
View(simulation2)
#> Error in as.data.frame(x): object 'simulation2' not found
```
Créé le 2020-11-25 par le package reprex (v0.3.0)
Réponses
Les noms de colonnes sont stockés dans strategy_list
, où vous voudrez incorporer i
:
strategy_list <- list("s_Win","s_WinH1", "s_WinH2",
"s_WinH1F1", "s_WinH2F2", "s_WinDerEx") %>%
stringr::str_c(i)
Parce que vous avez maintenant trois listes l
, vous voudrez aussi passer à l' utilisation ..1
, ..2
etc. au lieu de .x
et .y
(qui ne sont appropriés que pour deux séries d'arguments):
simulation <- pmap_dfc(l, ~ df %>%
transmute(!! ..1 := rlang::exec(..2, entries, ..3, field, win_payoff,
wager_amt, Winner, exacta_payoff))) %>%
bind_cols(df, .)
Remarque mineure : L' !!
opérateur est appelé "unquoting". Sans cela, transmute
créerait une colonne appelée .x
au lieu d'utiliser les noms stockés dans .x
. Voici un exemple qui démontre la différence:
x <- "result"
mtcars %>% transmute( x = "Hello World" )
# x
# 1 Hello World
# 2 Hello World
# ...
mtcars %>% transmute( !!x := "Hello World" )
# result
# 1 Hello World
# 2 Hello World
# ...
EDIT pour résoudre le ..2
problème: pour une raison quelconque, pmap
a des problèmes d'interprétation ..2
comme contenant une fonction. Une solution de contournement simple consiste à utiliser rlang::exec
pour exécuter cette fonction avec les arguments donnés:
simulation2 <- pmap_dfc(l, ~ df %>%
transmute(!! ..1 := rlang::exec(..2, x, y, ..3))) %>%
# ... as before
J'ai également mis à jour la réponse originale ci-dessus.