How do I add a third dynamic list element to my pmap_dfc statement

和自甴很熟 提交于 2020-12-13 03:33:58

问题


I have the following working code that utilizes two lists to produce simulation output:

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, .) 

Now I would like to run the simulation at several different skill levels, so I have added a loop and have tried to replace the skill input with i from the loop to create several variations of the 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, .)
}

Unfortunately, this is producing an error. I have tried several variations, but can't seem to get the code to work.

EDIT: Based upon Atem's post below, I have updated my code as follows:

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, .)  %>% 

Unfortunately, this is still producing an error. The problem appears to be with ..2 as this does not receive the same syntax highlighting as ..1 and ..3.

EDIT 2: To make this a bit simpler I have put together a simplified version of my question and included a reprex. Simulation1 with two lists works fine. Simulation2 with three lists and the loop fails with the error message: could not find function "..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
```

Created on 2020-11-25 by the reprex package (v0.3.0)


回答1:


The column names are stored in strategy_list, which is where you will want to incorporate i:

strategy_list <- list("s_Win","s_WinH1", "s_WinH2",
                      "s_WinH1F1", "s_WinH2F2", "s_WinDerEx") %>% 
                   stringr::str_c(i)

Because you now have three lists in l, you will also want to switch to using ..1, ..2, etc. instead of .x and .y (which are only appropriate for two sets of arguments):

simulation <- pmap_dfc(l, ~ df %>%
                      transmute(!! ..1 := rlang::exec(..2, entries, ..3, field, win_payoff, 
                                              wager_amt, Winner, exacta_payoff))) %>%
  bind_cols(df, .)

Minor note: The !! operator is known as "unquoting". Without it, transmute would create a column called .x instead of using the names stored in .x. Here's an example that demonstrates the difference:

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 to address the ..2 issue: For some reason, pmap has issues with interpreting ..2 as containing a function. A simple workaround is to use rlang::exec to execute that function with the given arguments:

simulation2 <- pmap_dfc(l, ~ df %>%
                      transmute(!! ..1 := rlang::exec(..2, x, y, ..3))) %>%
    # ... as before

I updated the original answer above as well.



来源:https://stackoverflow.com/questions/65005405/how-do-i-add-a-third-dynamic-list-element-to-my-pmap-dfc-statement

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!