如何使用参数组合将 mapply 与不等长度的输入集一起使用?

How to use mapply with sets of inputs of unequal lengths, using combinations of arguments?

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

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 运行s,对应于 3 个农场和 1000 个可能输入之间的所有组合3。

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

考虑第二次申请,您走在了正确的轨道上。你可以例如将你的 mapply 嵌套在 lapply 中,循环遍历你的 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

有一种简洁的方法可以使用 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