如何连续对函数的每个参数应用相同的更改?
How to apply succesively the same change to each argument of a function?
我想知道如何对我开发的模型进行弹性分析。
为此,我打算对模型的每个参数应用 10% 并测量输出的变化。
我写了一个简单的函数,包括所有参数作为参数。
我的挑战是我不知道如何使用应用函数或循环将此过程自动化到所有参数。
我们以一个虚拟函数为例:
model <- function(a=1, b=1, c=1){
result <- a+(10*b)+(100*c)
return(result)
}
我想对每个参数应用相同的更改(+10% 的值)并为每次迭代生成 运行。
例如,如果我必须手动执行它,它会像这样:
output_a <- model(a=1.1)
> 111.1
output_b <- model(b=1.1)
> 111
output_c <- model(c=1.1)
> 121
理想情况下,所有输出都在同一个数据框中,以便将来轻松处理它们。
对此有什么想法吗?也许我找不到现有的 post?
更改参数名称有点麻烦,但您可以使用 do.call()
语法来构建命名列表。您还可以使用 formalArgs()
获取函数参数的名称
所以你可以做类似的事情
lapply(formalArgs(model), function(arg) {
do.call("model", setNames(list(1.1), arg))
})
您还可以对 rlang
和 purrr
使用更整洁的方法
library(rlang)
library(purrr)
formalArgs(model) %>%
map(~exec(model, !!.x := 1.1))
创建所需值的网格,将其子集化为所需值,然后 Map
或 mapply
在其上或在 (3) 中直接生成它。
v <- c(1, 1.1)
# either of these would be ok
g <- expand.grid(a = v, b = v, c = v)
# g <- do.call("expand.grid", Map(function(x) v, c("a", "b", "c")))
g <- g[rowSums(g != 1) == 1, ]
# either of these would be ok
transform(g, result = mapply("model", g$a, g$b, g$c))
# transform(g, result = do.call("mapply", c("model", g)))
给予:
a b c result
2 1.1 1.0 1.0 111.1
3 1.0 1.1 1.0 112.0
5 1.0 1.0 1.1 121.0
2) 还有一些列表理解包(comprehenr, eList, listcompr)可以使用:
library(listcompr)
gen.data.frame(data.frame(a, b, c, result = model(a, b, c)),
a = v, b = v, c = v, (a != 1) + (b != 1) + (c != 1) == 1)
给予:
a b c result
1 1.1 1.0 1.0 111.1
2 1.0 1.1 1.0 112.0
3 1.0 1.0 1.1 121.0
3) diag 我们可以直接使用 diag
:
创建 g 矩阵
g <- diag(.1, 3) + 1
colnames(g) <- c("a", "b", "c")
cbind(g, result = apply(g, 1, function(x) model(x[1], x[2], x[3])))
给出这个矩阵:
a b c result
[1,] 1.1 1.0 1.0 111.1
[2,] 1.0 1.1 1.0 112.0
[3,] 1.0 1.0 1.1 121.0
我想知道如何对我开发的模型进行弹性分析。 为此,我打算对模型的每个参数应用 10% 并测量输出的变化。 我写了一个简单的函数,包括所有参数作为参数。
我的挑战是我不知道如何使用应用函数或循环将此过程自动化到所有参数。
我们以一个虚拟函数为例:
model <- function(a=1, b=1, c=1){
result <- a+(10*b)+(100*c)
return(result)
}
我想对每个参数应用相同的更改(+10% 的值)并为每次迭代生成 运行。 例如,如果我必须手动执行它,它会像这样:
output_a <- model(a=1.1)
> 111.1
output_b <- model(b=1.1)
> 111
output_c <- model(c=1.1)
> 121
理想情况下,所有输出都在同一个数据框中,以便将来轻松处理它们。 对此有什么想法吗?也许我找不到现有的 post?
更改参数名称有点麻烦,但您可以使用 do.call()
语法来构建命名列表。您还可以使用 formalArgs()
获取函数参数的名称
所以你可以做类似的事情
lapply(formalArgs(model), function(arg) {
do.call("model", setNames(list(1.1), arg))
})
您还可以对 rlang
和 purrr
library(rlang)
library(purrr)
formalArgs(model) %>%
map(~exec(model, !!.x := 1.1))
创建所需值的网格,将其子集化为所需值,然后 Map
或 mapply
在其上或在 (3) 中直接生成它。
v <- c(1, 1.1)
# either of these would be ok
g <- expand.grid(a = v, b = v, c = v)
# g <- do.call("expand.grid", Map(function(x) v, c("a", "b", "c")))
g <- g[rowSums(g != 1) == 1, ]
# either of these would be ok
transform(g, result = mapply("model", g$a, g$b, g$c))
# transform(g, result = do.call("mapply", c("model", g)))
给予:
a b c result
2 1.1 1.0 1.0 111.1
3 1.0 1.1 1.0 112.0
5 1.0 1.0 1.1 121.0
2) 还有一些列表理解包(comprehenr, eList, listcompr)可以使用:
library(listcompr)
gen.data.frame(data.frame(a, b, c, result = model(a, b, c)),
a = v, b = v, c = v, (a != 1) + (b != 1) + (c != 1) == 1)
给予:
a b c result
1 1.1 1.0 1.0 111.1
2 1.0 1.1 1.0 112.0
3 1.0 1.0 1.1 121.0
3) diag 我们可以直接使用 diag
:
g <- diag(.1, 3) + 1
colnames(g) <- c("a", "b", "c")
cbind(g, result = apply(g, 1, function(x) model(x[1], x[2], x[3])))
给出这个矩阵:
a b c result
[1,] 1.1 1.0 1.0 111.1
[2,] 1.0 1.1 1.0 112.0
[3,] 1.0 1.0 1.1 121.0