R:如何评估函数的形式(参数)?
R : How evaluate formals (arguments) of function?
我真的找遍了所有地方,但没有找到我的问题的答案:
广义问题:
- 如何在不启动 R 函数的情况下评估 R 函数的参数 (
formals()
)?
- 尽管 R 的 "Lazy evaluation",您如何评估 R 中的整个环境?
我的问题:
我想获取 R 中任何函数的参数的计算时间。例如,让我们考虑一个函数:
foo <- function(x, arg1 = 2, arg2 = arg3[1], arg3 = rnorm(10^6)) {
rnorm(10^7) # whatever time-consuming computation here
arg3^2
message("Too bad you had to launch the whole function !")
}
你会注意到困难的:
- 有些参数是必需的 (
x
),有些则不需要。 [结果:使用 formals()
不会 return x 的未计算表达式!]
- 一些参数是根据另一个函数计算的,在它之后定义(
arg2
是用 arg3
计算的)
期望的输出:
> system.time(foo(x=1))
Too bad you had to launch the whole function !
user system elapsed
1.835 0.000 1.573
> solution.function(foo, list(x=1))
The answer is in reality much lower ! It takes only 0.2 sec to compute the arguments !
广义解
很简单,似乎 as.list(environment)
实际上评估了整个环境并且 return 是一个列表!
我的最终解决方案
感谢 Martin Morgan 的帮助,我想出了这个解决方案,非常简单,并且解决了问题的所有限制:
foo2 <- foo #Just copy/paste the function, before modifying it
body(foo2) <- quote(as.list(environment())
foo2(x=2)
将 return 函数的所有参数(已评估)、必需参数 (x
) 以及默认参数 (arg1
、arg2
, arg3
)
您可以检查:system.time(foo2(x=1))
将 return 0.2 seconds
...仅 rnorm(10^6)
启动。
目前我的工作区中确实有一个名为 'c' 的矢量和一个名为 'd' 的数据框,所以我从以下位置获得:
lapply( formals(foo), eval)
#---------
$a
[1] 2
$b
function (..., recursive = FALSE) .Primitive("c")
$c
a b a2 b2
[1,] 1 NA 1 NA
[2,] 4 NA 4 NA
[3,] 9 NA 9 NA
[4,] 16 NA 16 NA
[5,] 25 NA 25 NA
$d
[1] 4
Warning messages:
1: In Ops.factor(left, right) : ‘^’ not meaningful for factors
2: In Ops.factor(left, right) : ‘^’ not meaningful for factors
这不完全是您 EvalFormals
返回的内容,但它似乎是我(一个经验丰富的 R 用户)所期望的。我不明白与测量执行时间的可能联系。
基本上是 hack,但复制你的函数
g = foo
用表达式替换函数体以计算每个参数,注意让错误继续存在
body(g) = quote(lapply(formals(), function(x) try(eval(x), TRUE))
或者也许
body(g) = quote(sapply(formals(), function(x) system.time(try(eval(x), TRUE))))
评价g()
(第一版)
> g()
$a
[1] 2
$b
[1] 16
$c
[1] 16
$d
[1] 4
$e
[1] "Error in eval(expr, envir, enclos) : object 'unknown_variable' not found\n"
attr(,"class")
[1] "try-error"
attr(,"condition")
<simpleError in eval(expr, envir, enclos): object 'unknown_variable' not found>
R 具有惰性计算,因此这不是衡量函数内部和外部时间的好方法。例如,f = function(y=Sys.sleep(Inf)) 1
returns 立即而不是从不。
必须单独处理 ...
个参数。
受上述答案的启发,以防万一有人在他们的全局环境中也需要这些变量(例如,用于对函数进行故障排除)。
Troubleshoot_function = function(fn, ...)
{
body(fn) = quote(expr = lapply(formals(),
FUN = function(x)
{
try(eval(x), TRUE)
}
)
)
ex = fn(...)
nm = names(ex)
invisible(
{
lapply(X = 1:length(ex),
FUN = function(i)
{
assign(x = nm[i],
value = ex[[i]],
envir = .GlobalEnv,
pos = -1
)
}
)
}
)
}
#example
Troubleshoot_function(foo)
ls()
[1] "arg1" "arg2" "arg3"
[4] "foo" "Troubleshoot_function" "x"
arg1
[1] 2
我真的找遍了所有地方,但没有找到我的问题的答案:
广义问题:
- 如何在不启动 R 函数的情况下评估 R 函数的参数 (
formals()
)? - 尽管 R 的 "Lazy evaluation",您如何评估 R 中的整个环境?
我的问题:
我想获取 R 中任何函数的参数的计算时间。例如,让我们考虑一个函数:
foo <- function(x, arg1 = 2, arg2 = arg3[1], arg3 = rnorm(10^6)) {
rnorm(10^7) # whatever time-consuming computation here
arg3^2
message("Too bad you had to launch the whole function !")
}
你会注意到困难的:
- 有些参数是必需的 (
x
),有些则不需要。 [结果:使用formals()
不会 return x 的未计算表达式!] - 一些参数是根据另一个函数计算的,在它之后定义(
arg2
是用arg3
计算的)
期望的输出:
> system.time(foo(x=1))
Too bad you had to launch the whole function !
user system elapsed
1.835 0.000 1.573
> solution.function(foo, list(x=1))
The answer is in reality much lower ! It takes only 0.2 sec to compute the arguments !
广义解
很简单,似乎 as.list(environment)
实际上评估了整个环境并且 return 是一个列表!
我的最终解决方案
感谢 Martin Morgan 的帮助,我想出了这个解决方案,非常简单,并且解决了问题的所有限制:
foo2 <- foo #Just copy/paste the function, before modifying it
body(foo2) <- quote(as.list(environment())
foo2(x=2)
将 return 函数的所有参数(已评估)、必需参数 (x
) 以及默认参数 (arg1
、arg2
, arg3
)
您可以检查:system.time(foo2(x=1))
将 return 0.2 seconds
...仅 rnorm(10^6)
启动。
目前我的工作区中确实有一个名为 'c' 的矢量和一个名为 'd' 的数据框,所以我从以下位置获得:
lapply( formals(foo), eval)
#---------
$a
[1] 2
$b
function (..., recursive = FALSE) .Primitive("c")
$c
a b a2 b2
[1,] 1 NA 1 NA
[2,] 4 NA 4 NA
[3,] 9 NA 9 NA
[4,] 16 NA 16 NA
[5,] 25 NA 25 NA
$d
[1] 4
Warning messages:
1: In Ops.factor(left, right) : ‘^’ not meaningful for factors
2: In Ops.factor(left, right) : ‘^’ not meaningful for factors
这不完全是您 EvalFormals
返回的内容,但它似乎是我(一个经验丰富的 R 用户)所期望的。我不明白与测量执行时间的可能联系。
基本上是 hack,但复制你的函数
g = foo
用表达式替换函数体以计算每个参数,注意让错误继续存在
body(g) = quote(lapply(formals(), function(x) try(eval(x), TRUE))
或者也许
body(g) = quote(sapply(formals(), function(x) system.time(try(eval(x), TRUE))))
评价g()
(第一版)
> g()
$a
[1] 2
$b
[1] 16
$c
[1] 16
$d
[1] 4
$e
[1] "Error in eval(expr, envir, enclos) : object 'unknown_variable' not found\n"
attr(,"class")
[1] "try-error"
attr(,"condition")
<simpleError in eval(expr, envir, enclos): object 'unknown_variable' not found>
R 具有惰性计算,因此这不是衡量函数内部和外部时间的好方法。例如,f = function(y=Sys.sleep(Inf)) 1
returns 立即而不是从不。
必须单独处理 ...
个参数。
受上述答案的启发,以防万一有人在他们的全局环境中也需要这些变量(例如,用于对函数进行故障排除)。
Troubleshoot_function = function(fn, ...)
{
body(fn) = quote(expr = lapply(formals(),
FUN = function(x)
{
try(eval(x), TRUE)
}
)
)
ex = fn(...)
nm = names(ex)
invisible(
{
lapply(X = 1:length(ex),
FUN = function(i)
{
assign(x = nm[i],
value = ex[[i]],
envir = .GlobalEnv,
pos = -1
)
}
)
}
)
}
#example
Troubleshoot_function(foo)
ls()
[1] "arg1" "arg2" "arg3"
[4] "foo" "Troubleshoot_function" "x"
arg1
[1] 2