FXQ*_*der 8 performance r function
方法1
f1 <- function(x)
{
# Do calculation xyz ....
f2 <- function(y)
{
# Do stuff...
return(some_object)
}
return(f2(x))
}
Run Code Online (Sandbox Code Playgroud)
方法2
f2 <- function(y)
{
# Do stuff...
return(some_object)
}
f3 <- function(x)
{
# Do calculation xyz ....
return(f2(x))
}
Run Code Online (Sandbox Code Playgroud)
假设f1并且f3两者都进行相同的计算并给出相同的结果.
使用方法1,呼叫,方法2,呼叫是否有任何明显的优势?f1()f3()
在以下情况下某种方法更有利:
大数据传入和/或传出 f2?
速度是一个大问题.例如,f1或f3在模拟中反复调用.
(方法1似乎在包中很常见,在另一个内部定义)
使用方法的一个优点f1是,f2将不存在之外f1,一旦f1完成了被称为(并f2仅在被称为f1或f3).
定义f2内部的好处f1:
f2只在内部可见f1,如果f2仅用于内部有用f1,虽然在包命名空间内这是有争议的,因为f2如果你在外面定义它就不会导出f2可以访问f1其中的变量,这可能被视为好事或坏事:
<<-用来实现memoization等东西.缺点:
f2需要在每次调用时重新定义f1,这会增加一些开销(不是很多开销,但绝对有)数据大小无关紧要,因为除非在任一情况下修改数据,否则R不会复制数据.如缺点所述,定义f2外部f1应该更快一些,特别是如果您多次重复一个相对较低的开销操作.这是一个例子:
> fun1 <- function(x) {
+ fun2 <- function(x) x
+ fun2(x)
+ }
> fun2a <- function(x) x
> fun3 <- function(x) fun2a(x)
>
> library(microbenchmark)
> microbenchmark(
+ fun1(TRUE), fun3(TRUE)
+ )
Unit: nanoseconds
expr min lq median uq max neval
fun1(TRUE) 656 674.5 728.5 859.5 17394 100
fun3(TRUE) 406 434.5 480.5 563.5 1855 100
Run Code Online (Sandbox Code Playgroud)
在这种情况下,我们保存为250ns(编辑:区别其实为200ns;无论你相信与否额外的一套{}是fun1有代价的另一个为50ns).不多,但如果内部功能更复杂或者您重复多次功能,可以加起来.
您通常会使用方法2.一些例外情况
功能关闭:
f = function() {
counter = 1
g = function() {
counter <<- counter + 1
return(counter)
}
}
counter = f()
counter()
counter()
Run Code Online (Sandbox Code Playgroud)
函数闭包使我们能够记住状态.
有时仅定义函数是很方便的,因为它们仅在一个地方使用.例如,在使用时optim,我们经常调整现有的功能.例如,
pdf = function(x, mu) dnorm(x, mu, log=TRUE)
f = function(d, lower, initial=0) {
ll = function(mu) {
if(mu < lower) return(-Inf)
else -sum(pdf(d, mu))
}
optim(initial, ll)
}
f(d, 1.5)
Run Code Online (Sandbox Code Playgroud)
该ll函数使用数据集d和下限.这很方便,因为这可能是我们使用/需要该ll功能的唯一时间.