【问题标题】:Using mapply inside a function(...)在函数内使用 mapply(...)
【发布时间】:2015-10-28 18:33:00
【问题描述】:

我正在尝试生成几个随机数系列,每个系列都有一组不同的参数。然后我想复制所有这些。我想要一个函数来执行此操作,它似乎应该是一个 1-liner,带有类似 rnorm() 的东西来生成数字,mapply() 来为几个参数集生成这些数字,replicate() 来重复整个过程。

为了实现这一点,我编写了一个函数,其 ... 参数我想对应于 mapply 中的 ...,但似乎 ...mapply 忽略。我有一些示例可以阐明我想要的输出以及问题:

 # Some values to be passed to the ... of mapply
 mus <- c(-30, 0, 30)
 sds <- c(0.1, 1, 10)

 # =================================
 # = What I want, if it would work =
 # =================================
 f <- function(n=3, ...){
    replicate(2, mapply(rnorm, MoreArgs=list(n=n), ...))
 }
 f(mean=mus, sd=sds) # Doesn't work :(

>, , 1
>
>           [,1]
>[1,] -0.4901243
>[2,]  0.8268027
>[3,] -0.4829781
>
>, , 2
>
>            [,1]
>[1,] -0.02025903
>[2,] -1.57011537
>[3,]  0.49234503


# ==========================================================
# = What I can currently get to work, but not style I want =
# ==========================================================
# I can't understand why f.inside is needed!
f2 <- function(n=3, ...){
    f.inside <- function() mapply(rand.gen, MoreArgs=list(n=n), ...)
    replicate(2, f.inside())
}
f2(mean=mus, sd=sds) # Desired output

>, , 1
>
>          [,1]        [,2]      [,3]
>[1,] -29.83762 -0.06138165  9.956601
>[2,] -30.04880  1.39123405 33.036675
>[3,] -29.94070 -1.15741513 19.337497
>[4,] -29.92360  0.74300731 38.741367
>[5,] -29.81723  0.84565813 22.261605
>
>, , 2
>
>          [,1]       [,2]     [,3]
>[1,] -30.01407 -0.5198845 20.85942
>[2,] -29.77586 -0.1705062 22.06274
>[3,] -29.96901 -0.4412471 21.42849
>[4,] -30.04079  0.4230790 28.35480
>[5,] -30.04794  0.3000821 50.09012

我猜我需要将... 包裹起来;我偶然尝试过alist()list()bquote()expression()as.call() 和其他几种失败的方法。

1) 为什么f() 中的mapply 似乎完全忽略了... 编辑:这是一个辅助问题,答案是“点不适用于复制”。好的,进入核心问题...

# =====================================
# = OK, Function for Refined Question =
# =====================================
f.edit <- function(n=3, ...){
    l <- list(...)
    replicate(2,mapply(rnorm, MoreArgs=list(n=n), l))
}
f.edit(mean=mus, sd=sds) # Doesn't work :(

2) 如何将对象的元素拆分为长度(对象)元素,并将它们作为单独的项目传递给mapply...

我需要在省略号方面做得更好。我真的被这个难住了。

【问题讨论】:

  • 更好的解决方案是使用rnorm 已经在其meansd 参数上矢量化的事实。例如,f&lt;-function(n,reps,mean,sd) {m&lt;-length(mean);aperm(array(rnorm(n*m*reps,mean,sd),c(m,n,reps)),c(2,1,3))}
  • @A.Webb不幸的是,我正在以arima.sim 的方式执行此操作;即,rnorm 可以是任何以n 为参数的数字生成函数。但你说得很好。
  • 关于f.edit 编辑,请改用function(n=3, ...){dots&lt;-list(...);replicate(2, do.call(mapply,c(list(FUN=rnorm),dots,list(MoreArgs=list(n=n)))))}
  • @A.Webb 就是这样!好的,我尝试过类似do.call 的方法,但我搞砸了;我仍在试图弄清楚为什么需要list()c() 的确切结构,但是asfaik,这是必要的。很好,谢谢。
  • @nongkrong 您的解决方案有效,但我仍在努力理解它。我以前从未使用过 ``` 符号,所以感谢您向我介绍它,以及我也不熟悉的 as.call。非常感谢!

标签: r mapply


【解决方案1】:

你在f.edit尝试的时尚...

  • 您可以构造参数列表并使用mapply 执行do.call

    function(n=3, ...){
      dots<-list(...);
      replicate(2,do.call(mapply,c(list(FUN=rnorm),dots,list(MoreArgs=list(n=n)))))
    }
    
  • 或者,提取参数并直接调用

    function(n=3, ...){
      dots<-list(...);
      replicate(2,mapply(rnorm,dots$mean,dots$sd,MoreArgs=list(n=n)))
    }
    

在任何一种情况下,您都强制在正确的环境中评估 ...,就像在您的 f2MrFlick's alternative 中所做的那样。

f.edit 的问题是rnorm 被称为rnorm(n,list(means=mus,sd=sds)) 而不是rnorm(n,means=mu,sd=sds)


但是,在这种情况下,您可以考虑使用 rnorm 已经对其均值和 sd 参数进行矢量化的事实

function(n,reps,mean,sd) {
  m<-length(mean);
  aperm(array(rnorm(n*m*reps,mean,sd),c(m,n,reps)),c(2,1,3))
}

【讨论】:

  • 所以在f.edit 中,有没有办法对l 做些什么来让它工作?我只是想解决这个问题。我知道我只传递了 1 个参数,而不是几个......但是我可以把那个 1 分成几个吗?我想这就是你对 do.call 所做的事情。
  • @rbatt 看看上面的编辑是否清楚f.edit中发生的事情。
【解决方案2】:

问题是您不能将...replicate 一起使用,正如已经讨论过的here

我已经认为您找到了使用辅助函数 f.inside() 来获取 ... 术语的最易读的替代方法。

另一种选择是避免使用replicate 并使用lapply(您最终会忽略索引值)

f3 <- function(n=3, ...){
    lapply(1:2, function(i, ...) mapply(rnorm, MoreArgs=list(n=n), ...), ...)
}
f3(mean=mus, sd=sds)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-05-22
    • 1970-01-01
    • 2015-07-01
    • 2015-06-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多