Jak dodać trzeci element listy dynamicznej do mojej instrukcji pmap_dfc
Mam następujący kod roboczy, który wykorzystuje dwie listy do tworzenia danych wyjściowych symulacji:
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, .)
Teraz chciałbym uruchomić symulację na kilku różnych poziomach umiejętności, więc dodałem pętlę i próbowałem zastąpić dane wejściowe umiejętności i z pętli, aby utworzyć kilka odmian symulacji:
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, .)
}
Niestety powoduje to błąd. Próbowałem kilku odmian, ale nie mogę uruchomić kodu.
EDYCJA: Na podstawie poniższego postu Atem zaktualizowałem mój kod w następujący sposób:
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, .) %>%
Niestety nadal powoduje to błąd. Wydaje się, że problem dotyczy ..2, ponieważ nie ma on takiego samego podświetlania składni jak ..1 i ..3.
EDYCJA 2: Aby to trochę uprościć, przygotowałem uproszczoną wersję mojego pytania i dołączyłem reprex. Symulacja1 z dwoma listami działa dobrze. Simulation2 z trzema listami i pętla kończy się niepowodzeniem i komunikatem o błędzie: nie można znaleźć funkcji „..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
```
Utworzono 25.11.2020 przez pakiet reprex (v0.3.0)
Odpowiedzi
Nazwy kolumn są przechowywane w strategy_list
, w którym chcesz uwzględnić i
:
strategy_list <- list("s_Win","s_WinH1", "s_WinH2",
"s_WinH1F1", "s_WinH2F2", "s_WinDerEx") %>%
stringr::str_c(i)
Bo teraz masz trzy listy w l
, chcemy też, aby przełączyć się za pomocą ..1
, ..2
itd zamiast .x
a .y
(które są właściwe tylko dla dwóch zestawów argumentów):
simulation <- pmap_dfc(l, ~ df %>%
transmute(!! ..1 := rlang::exec(..2, entries, ..3, field, win_payoff,
wager_amt, Winner, exacta_payoff))) %>%
bind_cols(df, .)
Drobna uwaga : !!
operator jest znany jako „unquoting”. Bez tego transmute
utworzyłoby kolumnę o nazwie .x
zamiast używania nazw przechowywanych w .x
. Oto przykład, który pokazuje różnicę:
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
# ...
EDYTUJ w celu rozwiązania ..2
problemu: z jakiegoś powodu pmap
ma problemy z interpretacją ..2
jako zawierającą funkcję. Prostym obejściem jest użycie rlang::exec
do wykonania tej funkcji z podanymi argumentami:
simulation2 <- pmap_dfc(l, ~ df %>%
transmute(!! ..1 := rlang::exec(..2, x, y, ..3))) %>%
# ... as before
Zaktualizowałem również oryginalną odpowiedź powyżej.