【问题标题】:R purrr:::pmap: how to refer to input arguments by name?R purrr:::pmap:如何按名称引用输入参数?
【发布时间】:2017-06-11 10:25:19
【问题描述】:

我正在使用带有三个输入的 R purrr:::pmap。不清楚如何在 formula 调用中明确引用这些输入?使用 map2 时,formula 调用为 ~ .x + .y。但是使用pmap的时候怎么办呢?

http://r4ds.had.co.nz/lists.html复制哈德利的例子

library(purrr)
mu <- list(5, 10, -3)
sigma <- list(1, 5, 10)
n <- list(1, 3, 5)

args2 <- list(mean = mu, sd = sigma, n = n)
pmap(args2, rnorm)

如果我想在调用rnorm 时显式引用输入参数,我可以使用:

pmap(args2, function(mean, sd, n) rnorm(n, mean, sd))

但是假设我想用 formula 方法来做到这一点。我怎么做?例如,这不起作用:

pmap(args2, ~rnorm(n=.n, mean=.mean, sd=.sd))

谢谢!!

【问题讨论】:

    标签: r purrr tidyverse


    【解决方案1】:

    pmap 似乎无法通过公式界面中的名称访问列表中的参数。 您可以签入https://github.com/hadley/purrr/issues/203

    例如你可以这样做:

    pmap(list(1:2, 5:6), ~ .x + .y)
    

    因此,列表的第一个元素由.x 引用,第二个元素由.y 引用。 但是,如果您尝试将列表的参数命名为

    pmap(list(a = 1:2, b =  5:6), ~ .a + .b)
    

    那么你会遇到错误:

    Error in .f(a = .l[[c(1L, i)]], b = .l[[c(2L, i)]], ...) : 
      unused arguments (a = .l[[c(1, i)]], b = .l[[c(2, i)]])
    

    我认为在函数pmap的公式界面中,如果您想使用公式界面而不使用function(mean , sd, n),您可以做的最好的事情是:

    1. 不要命名列表中的元素
    2. 不要使用两个以上的参数(为了使用隐式名称.x.y

    因此,您可以使用这样来修复您想要的第三个参数n(例如n = 4)的值,然后运行:

    mu <- list(5, 10, -3)
    sigma <- list(1, 5, 10)
    set.seed(1)
    pmap(list(mu,sigma), ~ rnorm(mean = .x, sd = .y, n = 4))
    

    哪个会返回:

    [[1]]
    [1] 4.373546 5.183643 4.164371 6.595281
    
    [[2]]
    [1] 11.647539  5.897658 12.437145 13.691624
    
    [[3]]
    [1]  2.7578135 -6.0538839 12.1178117  0.8984324
    
    [[4]]
    [1]  9.136278  4.355900 14.374793 10.865199
    

    【讨论】:

    • 非常感谢!很高兴特别看到链接!不幸的是,就我而言,仅使用 2 个输入并不是真正的解决方案:-(
    • 是的,我同意,仅使用 2 个输入的危害较小,但仍不能令人满意。至少你可以使用function(mean, sd, n)的方法;顺便说一句,您绝对要使用公式方法吗?
    【解决方案2】:

    由于version 0.2.3,你可以使用..1..2..3等等:

    pmap(args2, ~ rnorm(..3, ..1, ..2))
    

    但是...我已经遇到了这种语法的问题,例如replicate:

    pmap(list(1, 2), ~ replicate(n = ..1, expr = ..2))
    # Error in FUN(X[[i]], ...) : the ... list does not contain 2 elements
    

    可能是因为:

    print(replicate)
    # function (n, expr, simplify = "array") 
    #   sapply(integer(n), eval.parent(substitute(function(...) expr)), 
    #          simplify = simplify)
    

    似乎substitute() 中的function(...) expr..2 配合得不好,被解释为... 的第二个元素为空。

    请注意,pmap(list(1, 2), ~ replicate(n = ..1, expr = .y)) 仍然有效。

    【讨论】:

      【解决方案3】:

      你可以使用with(...)来解决这个问题:

      pmap(args2, ~with(list(...),rnorm(n, mean, sd)))
      # [[1]]
      # [1] 2.733528
      # 
      # [[2]]
      # [1] 4.0967533 6.4926143 0.6083532
      # 
      # [[3]]
      # [1]  1.8836592 -0.2090425 -4.0030168  1.1834931  3.2771316
      

      更多解释在这里:Harnessing .f list names with purrr::pmap

      【讨论】:

      • 优雅的解决方案,不错!
      猜你喜欢
      • 2020-01-10
      • 2021-06-21
      • 2018-12-09
      • 1970-01-01
      • 1970-01-01
      • 2019-10-31
      • 1970-01-01
      • 2019-03-12
      • 2019-10-21
      相关资源
      最近更新 更多