【问题标题】:What is the proper way to allow arguments to pass via ... through multiple functions with purrr map什么是允许参数通过...通过具有 purrr 映射的多个函数的正确方法
【发布时间】:2023-03-26 18:05:01
【问题描述】:

考虑以下三个函数:

f1 <- function(df, ...) {
  df %>%
    mutate(
      model = map(.$splits, ~ f2(.))
    )
}

f2 <- function(split_df) {
  split_df %>%
    analysis() %>% 
    nest() %>%
    mutate(
      forecast = map(data, ~ f3(.$actuals))
    )
}

f3 <- function(x, N = 3, fn = mean, window_size = 6, ...) {
  # stuff
}

我在更大的管道中运行这些函数,但我的问题的要点是:我想将参数传递给f3()(例如,在以下代码行中将fn = mean 更改为fn = median

df_resamples %>%
  mutate(
    result = .$resamples %>% map(~ f1(.))
  )

但是,以下都没有返回正确的结果:

# INCORRECT
df_resamples %>%
  mutate(
    result = .$resamples %>% map(~ f1(.), fn = median)
  )
# ALSO INCORRECT
df_resamples %>%
  mutate(
    result = .$resamples %>% map(~ f1(., fn = median))
  )

如果我在f2 中硬编码fn,我会得到正确的结果:

f2_good <- function(split_df) {
  split_df %>%
    analysis() %>% 
    nest() %>%
    mutate(
      forecast = map(data, ~ f3(.$actuals, fn = median))
    )
}

如果我从f1 传递...,为什么我不能传递fn = medianf3

注意:我能够解决将参数传递给 f1f2 的问题,但这感觉不是很干,我想我可以使用省略号来规避这种方法:

f1 <- function(df, N = 3, fn = mean, window_size = 6) {
  df %>%
    mutate(
      model = map(.$splits, ~ f2(., N = N, fn = fn, window_size = window_size))
    )
}

f2 <- function(split_df, N = 3, fn = mean, window_size = 6) {
  split_df %>%
    analysis() %>% 
    nest() %>%
    mutate(
      forecast = map(data, ~ f3(.$actuals, N = N, fn = fn, window_size = window_size))
    )
}

做到以上几点,我可以做到:

df_resamples %>%
  mutate(
    result = .$resamples %>% map(~ f1(., fn = median))
  )

并获得预期的结果,但我必须将默认值传递给 f1f2...

【问题讨论】:

    标签: r parameter-passing purrr


    【解决方案1】:

    您是否尝试将... 添加到每个签名和函数调用中,例如:

    f1 <- function(df, ...) {
      df %>%
        mutate(
          model = map(.$splits, ~ f2(., ...))
        )
    }
    
    f2 <- function(split_df, ...) {
      split_df %>%
        analysis() %>% 
        nest() %>%
        mutate(
          forecast = map(data, ~ f3(.$actuals, ...))
        )
    }
    
    f3 <- function(x, N = 3, fn = mean, window_size = 6, ...) {
      # stuff
    }
    

    然后调用

    df_resamples %>%
      mutate(
        result = .$resamples %>% map(~ f1(., fn = median))
      )
    

    编辑:玩具示例

    f1 <- function(x, ...) f2(x, ...)
    f2 <- function(x, ...) f3(x, ...)
    f3 <- function(x, fn = mean, na.rm = FALSE, ...) fn(x, na.rm = na.rm) 
    
    f1(c(1,2,3,NA), fn = max, na.rm = TRUE)
    

    【讨论】:

    • 是的,但是由于一个奇怪的错误而失败 - 请参阅我上面关于可行但感觉不是很干燥的解决方案的编辑。
    • 我的建议是将...f1 传递到f3。因此将map(.$splits, ~ f2(.)) 更改为map(.$splits, ~ f2(., ...),将f2 &lt;- function(split_df) 更改为f2 &lt;- function(split_df, ...),将map(data, ~ f3(.$actuals)) 更改为map(data, ~ f3(.$actuals, ...))。如果它不起作用,你能把错误发给我吗?
    • 我明白你在做什么,这是我尝试过的第一个替代方案之一,但它最终导致 f3 函数出错:` (n + 1) 中的错误: (n + N) : NA/NaN argument` -- 进行回溯/调试,看起来,由于某种原因,在尝试这种方法时,data.frame / tibble 被传递给f3,而不是预期的向量通过.$actuals.
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-02-02
    • 2013-03-06
    • 2022-11-20
    • 2014-04-28
    • 1970-01-01
    • 2014-01-15
    相关资源
    最近更新 更多