【问题标题】:How to use mapply with sets of inputs of unequal lengths, using combinations of arguments?如何使用参数组合将 mapply 与长度不等的输入集一起使用?
【发布时间】:2021-05-20 15:10:24
【问题描述】:

我正在尝试找到一种使用自定义函数运行多个模拟的方法。 每个模拟使用不同的输入值,基于现实生活中的测量。 假设这个函数可以预测大田作物的产量。

predict <- function(input1, input2, input3){
   output = input1 + input2 + input3
   return(output)
   }

我知道如何使用 mapply 在参数列表上运行此函数,但我找不到如何使用不同的输入组合(长度不等的列表)。 为了说明,我有一个数据框(带有虚拟数字),每一行对应一个农场,每一列对应一个输入参数(除了第一个,它是农场代码)。

df <- data.frame("Farm" = 1:3, "input1" = c(10, 20 , 30), "input2" = c(100, 200, 300))
df

现在,正如您所注意到的,我在此数据框中没有第三个参数“input3”。 对于这个特定的论点,我有 1000 个不同的可能值。

all_possible_input3 <- seq(1:1000) # dummy values

我想为观察到的农场参数和 1000 个不同的可能值之间的每个组合运行预测函数。 为了展示第一个组合的几个示例,每个组合看起来像这样:

# For Farm 1:
Farm1_run1 <- predict(input1 = 10, input2 = 100, input3 = 1)
Farm1_run2 <- predict(input1 = 10, input2 = 100, input3 = 2)
Farm1_run3 <- predict(input1 = 10, input2 = 100, input3 = 3)
# ... and goes on to use the 1000 values for the third argument.

# For Farm 2:
Farm2_run1 <- predict(input1 = 20, input2 = 200, input3 = 1)
Farm2_run2 <- predict(input1 = 20, input2 = 200, input3 = 2)
Farm2_run3 <- predict(input1 = 20, input2 = 200, input3 = 3)
# ... and goes on to use the 1000 values for the third argument.

# For Farm 3:
Farm3_run1 <- predict(input1 = 30, input2 = 300, input3 = 1)
Farm3_run2 <- predict(input1 = 30, input2 = 300, input3 = 2)
Farm3_run3 <- predict(input1 = 30, input2 = 300, input3 = 3)
# ... and goes on to use the 1000 values for the third argument.

总共应该产生 3000 次运行,对应于 3 个农场之间的所有组合和 1000 个可能的输入 3。

我知道如何使用 mapply 在多个参数列表上循环一个函数,但是如何处理长度不等的列表呢? 我曾考虑在第一个函数之上添加另一个 apply 函数,但我还没有找到解决方案。 也许首先拆分数据帧,然后将每一行组合到每个可能的 input3,然后将该函数应用于每一行输入? 我希望我的例子足够清楚...... 你能帮忙吗?

【问题讨论】:

    标签: r function iteration apply repeat


    【解决方案1】:

    通过考虑第二次申请,您走在了正确的轨道上。你可以例如将mapply 嵌套在lapply 中,该all_possible_input3 循环遍历您的all_possible_input3

    predict <- function(input1, input2, input3){
      output = input1 + input2 + input3
      return(output)
    }
    
    df <- data.frame("Farm" = 1:3, "input1" = c(10, 20 , 30), "input2" = c(100, 200, 300))
    df
    #>   Farm input1 input2
    #> 1    1     10    100
    #> 2    2     20    200
    #> 3    3     30    300
    
    all_possible_input3 <- 1:10
    
    farm_runs <- lapply(all_possible_input3, function(input3) {
      mapply(predict, input1 = df$input1, input2 = df$input2, input3 = input3)
    })
    farm_runs
    #> [[1]]
    #> [1] 111 221 331
    #> 
    #> [[2]]
    #> [1] 112 222 332
    #> 
    #> [[3]]
    #> [1] 113 223 333
    #> 
    #> [[4]]
    #> [1] 114 224 334
    #> 
    #> [[5]]
    #> [1] 115 225 335
    #> 
    #> [[6]]
    #> [1] 116 226 336
    #> 
    #> [[7]]
    #> [1] 117 227 337
    #> 
    #> [[8]]
    #> [1] 118 228 338
    #> 
    #> [[9]]
    #> [1] 119 229 339
    #> 
    #> [[10]]
    #> [1] 120 230 340
    

    【讨论】:

    • 感谢您的快速回答。它就像一个魅力!
    【解决方案2】:

    有一种简洁的方法可以使用outer 执行此操作,该方法将FUN 横向应用于其参数。只需将 Vectorize 函数调用的框架放入 outer 中,如下所示:

    FUN <- Vectorize(function(i, j) with(df, my_pred(input1[i], input2[i], a.input3[j])))
    res1 <- outer(1:nrow(df), seq(a.input3), FUN)
    res1
    #      [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
    # [1,]  111  112  113  114  115  116  117  118  119   120
    # [2,]  221  222  223  224  225  226  227  228  229   230
    # [3,]  331  332  333  334  335  336  337  338  339   340
    

    数据:

    my_pred <- function(input1, input2, input3) {  ## renamed because `predict` is actually used
      output <- input1 + input2 + input3
      return(output)
    }
    
    df <- structure(list(Farm = 1:3, input1 = c(10, 20, 30), input2 = c(100, 
    200, 300)), class = "data.frame", row.names = c(NA, -3L))
    
    a.input3 <- seq(1:10)  ## shortened for example
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-10-26
      • 1970-01-01
      • 2017-10-13
      • 2019-05-29
      • 2022-11-05
      相关资源
      最近更新 更多