【问题标题】:Loop over function that has three arguments, mapply/sapply/for loops not working?循环具有三个参数的函数,mapply/sapply/for 循环不起作用?
【发布时间】:2019-03-06 22:09:24
【问题描述】:

我试图循环一个具有三个参数的函数,但 lapply 和 mapply 都没有提供正确的解决方案。这里的目标是根据三个参数(num、resp、cdr)的所有可能组合获得所有可能的结果。如果您看到下面的函数,这里的目标是计算所有三个级别的 num 的 n(保持 resp 和 cdr 常量),对于所有三个级别的 resp(保持 num 和 @987654331 @常量),并且对于cdr的所有三个级别(保持resp和num常量)。但正如您从输出中看到的那样,lapply 和 mapply 都没有在这里提供正确的答案。

尝试使用嵌套的for 循环来执行此操作也没有成功(尽管我在使用循环方面不是那么好,所以如果它让我得到正确的答案,我愿意接受基于循环的解决方案)。

最小可重现示例:

set.seed(124)
num <- c(10, 20, 30)
resp <- sample(100:200, 3)
cdr <- 3:5

my_fun <- function(num, resp, cdr){
 n <- ((num * resp) / cdr)   
}  

sapply(num, my_fun, resp, cdr)
     [,1] [,2] [,3]
[1,]  360  720 1080
[2,]  350  700 1050
[3,]  302  604  906

mapply(my_fun, num, resp, cdr)
[1] 360 700 906

【问题讨论】:

  • 或许expand.grid(num, resp, cdr)?
  • @H1 运行 expand.grid(num, resp, cdr) 但据我所知,它没有应用该函数来为 27 种组合中的每一种获得 n 的计算?
  • @rowbust 我不确定您的预期输出应该是什么(例如 3d array,扁平化 data.frame,...?)。您可以编辑您的帖子以包含它吗?
  • @H1 只是意味着expand.grid() 会给你所有 27 种组合,然后你可以在上面正确使用mapply(或等效的东西)。
  • @rowbust BTW 确保你的函数返回一些东西。

标签: r lapply sapply mapply


【解决方案1】:

你可以试试:

df <- expand.grid(data.frame(num, resp, cdr))
with(df, (num * resp) / cdr)

   num resp cdr         n
1   10  151   3  503.3333
2   20  151   3 1006.6667
3   30  151   3 1510.0000
4   10  176   3  586.6667
5   20  176   3 1173.3333
...

【讨论】:

  • 这似乎也有效do.call(my_fun, expand.grid(data.frame(num, resp, cdr))) +1
【解决方案2】:

基于 purrr/dplyr 的解决方案是:

set.seed(124)
num <- c(10, 20, 30)
resp <- sample(100:200, 3)
cdr <- 3:5

my_fun <- function(num, resp, cdr){
 ((num * resp) / cdr)   
} 

args <- list(num = num, resp = resp, cdr = cdr)
args %>% 
  purrr::cross_df() %>% 
  dplyr::mutate(res = my_fun(num, resp, cdr))

【讨论】:

    【解决方案3】:
    # gen data
    set.seed(124)
    num  <- c(10, 20, 30)
    resp <- sample(100:200, 3)
    cdr  <- 3:5
    
    # function (written with one input vector)
    my_fun <- function(x){
      x[1] * x[2] / x[3]  
    } 
    
    # used expand.grid() and apply() to 
    # eval function on all combos of num, resp, cdr
    opts <- expand.grid(num, resp, cdr)
    res  <- apply(opts, 1, my_fun)
    cbind(opts, res)
    

    【讨论】:

    • apply 似乎不是一个好的选择,因为 OP 的函数在其参数中是矢量化的。
    • 那么只需:opts &lt;- expand.grid(num, resp, cdr); my_fun(opts[1], opts[2], opts[3]) 以及 OP 的 my_fun 定义。
    • 是的!查看do.call - 在这种情况下非常有用(且高效)。
    • 是的 - 坦率地说,尽管我发了帖子,但我喜欢 @markus 的解决方案,do.call() best
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-12-04
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多