Function 从函数返回列表中的函数

Function 从函数返回列表中的函数,function,r,Function,R,我搜索了这个问题,但找到的答案不够具体 我正在清理旧代码,我正在努力确保下面的代码相对干净,并希望以后它不会咬到我的屁股 我的问题是关于通过函数传递函数。查看以下绘图语句的y部分。goodf[[1]]x这玩意儿行得通,但我是在自找麻烦吗?如果是,有没有更干净的方法 此外,如果多次调用goo函数,例如在蒙特卡罗分析中,这会加载R的内部构件还是可能导致某种类型的环境问题 编辑2011年2月21日以下代码只是一个示例。真正的函数goo在到达approxfun语句之前有很多代码 #Build a dat

我搜索了这个问题,但找到的答案不够具体

我正在清理旧代码,我正在努力确保下面的代码相对干净,并希望以后它不会咬到我的屁股

我的问题是关于通过函数传递函数。查看以下绘图语句的y部分。goodf[[1]]x这玩意儿行得通,但我是在自找麻烦吗?如果是,有没有更干净的方法

此外,如果多次调用goo函数,例如在蒙特卡罗分析中,这会加载R的内部构件还是可能导致某种类型的环境问题

编辑2011年2月21日以下代码只是一个示例。真正的函数goo在到达approxfun语句之前有很多代码

#Build a dataframe
df <- data.frame(a=c(1, 2, 3, 4, 5), b=c(4, 3, 1, 2, 6))

#Build a function that passes a function
goo <- function(inp.df) {
  out.fun <- approxfun(x=inp.df$a, y=inp.df$b, yright=max(inp.df$b), method="linear", f=1)
  list(out.fun, inp.df$a[5], inp.df$b[5])
}

#Set up the plot range
x <- seq(1, 4.3, 0.01)

#Plot the function
plot(x, goo(df)[[1]](x), type="l", xlim=c(0, goo(df)[[2]]), ylim=c(0, goo(df)[[3]]), lwd=2, col="red")
grid()



goo(df)

[[1]]
function (v) 
.C("R_approxfun", as.double(x), as.double(y), as.integer(n), 
    xout = as.double(v), as.integer(length(v)), as.integer(method), 
    as.double(yleft), as.double(yright), as.double(f), NAOK = TRUE, 
    PACKAGE = "stats")$xout
<environment: 0219d56c>

[[2]]
[1] 5

[[3]]
[1] 6

我将删除一个级别的函数处理,并将输入数据保留在函数生成之外。然后您可以将您的函数排除在goo之外,并且只调用approxfun一次

它还可以推广到任意大小的输入数据帧,而不仅仅是一个有5行的数据帧

#Build a dataframe
df <- data.frame(a=c(1, 2, 3, 4, 5), b=c(4, 3, 1, 2, 6))

#Build a function
fun <- approxfun(x = df$a, y = df$b, yright=max(df$b), method="linear", f = 1)

#Set up the plot range
x <- seq(1, 4.3, 0.01)

#Plot the function
plot(x, fun(x), type="l", xlim=c(0, max(df$a)), ylim=c(0, max(df$b)), lwd=2, col="red")

这可能不是您最终需要的,但它确实消除了一定程度的复杂性,并提供了一个更清晰的起点

我将删除一个级别的函数处理,并将输入数据保留在函数生成之外。然后您可以将您的函数排除在goo之外,并且只调用approxfun一次

它还可以推广到任意大小的输入数据帧,而不仅仅是一个有5行的数据帧

#Build a dataframe
df <- data.frame(a=c(1, 2, 3, 4, 5), b=c(4, 3, 1, 2, 6))

#Build a function
fun <- approxfun(x = df$a, y = df$b, yright=max(df$b), method="linear", f = 1)

#Set up the plot range
x <- seq(1, 4.3, 0.01)

#Plot the function
plot(x, fun(x), type="l", xlim=c(0, max(df$a)), ylim=c(0, max(df$b)), lwd=2, col="red")

这可能不是您最终需要的,但它确实消除了一定程度的复杂性,并提供了一个更清晰的起点

在不确切了解代码的情况下,很难给出具体的建议,但这里有几点需要考虑:

真的有必要在goo的返回值中包含goo的输入数据吗?换句话说,你能让goo成为一个简单的工厂,只返回一个函数吗?在您的示例中,至少plot函数已经具有确定限制所需的所有数据。 如果这是不可能的,那么继续使用这个模式,但是给出goo返回值的元素的描述性名称,这样当您引用它们时,至少可以很容易地看到发生了什么。例如,goodf$approxx。如果在代码中广泛使用此结构,请考虑将其构造为S3类。 最后,不要在plot函数中多次调用goodf,只是为了得到不同的元素。当你这样做的时候,你每次都会调用goo,正如你所说的,它会执行很多代码。此外,每个调用都有自己的环境,其中包含一个输入数据的副本,尽管R足够聪明,可以在一定程度上减少复制,并使用相同的df物理实例。相反,只需调用goo一次,将其值赋给一个变量,然后引用该变量。
在不确切了解代码的情况下,很难给出具体的建议,但这里有几点需要考虑:

真的有必要在goo的返回值中包含goo的输入数据吗?换句话说,你能让goo成为一个简单的工厂,只返回一个函数吗?在您的示例中,至少plot函数已经具有确定限制所需的所有数据。 如果这是不可能的,那么继续使用这个模式,但是给出goo返回值的元素的描述性名称,这样当您引用它们时,至少可以很容易地看到发生了什么。例如,goodf$approxx。如果在代码中广泛使用此结构,请考虑将其构造为S3类。 最后,不要在plot函数中多次调用goodf,只是为了得到不同的元素。当你这样做的时候,你每次都会调用goo,正如你所说的,它会执行很多代码。此外,每个调用都有自己的环境,其中包含一个输入数据的副本,尽管R足够聪明,可以在一定程度上减少复制,并使用相同的df物理实例。相反,只需调用goo一次,将其值赋给一个变量,然后引用该变量。
这在大型蒙特卡罗模拟中可能不是更好,但对于更简单的情况,将x和y范围作为已创建函数的输出属性,而不是包含在已创建函数的列表中,可能会更清楚。正如达沃尔提到的,这样一来,goo是一个更直接的工厂。您还可以使用S3将函数的结果设置为对象,以便更简单地绘制

goo <- function(inp.df) {
  out.fun <- approxfun(x=inp.df$a, y=inp.df$b, yright=max(inp.df$b), 
                       method="linear", f=1)
  xmax <- inp.df$a[5]
  ymax <- inp.df$b[5]
  function(...) {
    structure(data.frame(x=x, y = out.fun(...)), 
              limits=list(x=xmax, y=ymax), 
              class=c("goo","data.frame"))
   }
}

plot.goo <- function(x, xlab="x", ylab="approx",  
                     xlim=c(0, attr(x, "limits")$x), 
                     ylim=c(0, attr(x, "limits")$y), 
                     lwd=2, col="red", ...) {
  plot(x$x, x$y, type="l", xlab=xlab, ylab=ylab, 
       xlim=xlim, ylim=ylim, lwd=lwd, col=col, ...)
}
然后,要为数据帧创建函数,请执行以下操作:

df <- data.frame(a=c(1, 2, 3, 4, 5), b=c(4, 3, 1, 2, 6))
goodf <- goo(df)
x <- seq(1, 4.3, 0.01) 
goodfx <- goodf(x)
plot(goodfx)
要在向量上使用它,您需要:

df <- data.frame(a=c(1, 2, 3, 4, 5), b=c(4, 3, 1, 2, 6))
goodf <- goo(df)
x <- seq(1, 4.3, 0.01) 
goodfx <- goodf(x)
plot(goodfx)

这在大型蒙特卡罗模拟中可能不是更好,但对于更简单的情况,将x和y范围作为已创建函数的输出属性,而不是包含在已创建函数的列表中,可能会更清楚。正如达沃尔提到的,这样一来,goo是一个更直接的工厂。您还可以使用S3将函数的结果设置为对象,这样就可以打印它 更简单地说

goo <- function(inp.df) {
  out.fun <- approxfun(x=inp.df$a, y=inp.df$b, yright=max(inp.df$b), 
                       method="linear", f=1)
  xmax <- inp.df$a[5]
  ymax <- inp.df$b[5]
  function(...) {
    structure(data.frame(x=x, y = out.fun(...)), 
              limits=list(x=xmax, y=ymax), 
              class=c("goo","data.frame"))
   }
}

plot.goo <- function(x, xlab="x", ylab="approx",  
                     xlim=c(0, attr(x, "limits")$x), 
                     ylim=c(0, attr(x, "limits")$y), 
                     lwd=2, col="red", ...) {
  plot(x$x, x$y, type="l", xlab=xlab, ylab=ylab, 
       xlim=xlim, ylim=ylim, lwd=lwd, col=col, ...)
}
然后,要为数据帧创建函数,请执行以下操作:

df <- data.frame(a=c(1, 2, 3, 4, 5), b=c(4, 3, 1, 2, 6))
goodf <- goo(df)
x <- seq(1, 4.3, 0.01) 
goodfx <- goodf(x)
plot(goodfx)
要在向量上使用它,您需要:

df <- data.frame(a=c(1, 2, 3, 4, 5), b=c(4, 3, 1, 2, 6))
goodf <- goo(df)
x <- seq(1, 4.3, 0.01) 
goodfx <- goodf(x)
plot(goodfx)

我的例子只是一个例子。实际上,在approxfun之前,函数goo中有很多代码。降低级别不是一个选项。好的,这将是有用的信息开始。如果您真正的goo确实经常被调用,并且对每个小数据集只运行approxfun一次,那么您最好使用approx并传递估计的数据。如果同一数据真的被多次调用,你可能需要重新思考原因。在我看来,这里没有足够的上下文。这可能不容易理解,但如果我提供了goo的内部结构,它会让我不再关注我所担心的内容。函数goo接收大量数据并构建一个函数和参数,这些函数和参数将被多次使用。goo将被一次又一次地调用,以填充许多函数/参数。将根据MC的要求调用所有这些函数/参数,以估计系统的各种特性。我目前正在跟踪内存使用情况,但我担心,当我将其放大时,可能会有一些环境/语法问题困扰着我。在上面的评论中没有空间,所以……正如您所想象的,在goo生成了许多不同的函数/参数之后,我必须管理这一堆。这带来了一些我还没有问过的其他问题。我的例子只是一个例子。实际上,在approxfun之前,函数goo中有很多代码。降低级别不是一个选项。好的,这将是有用的信息开始。如果您真正的goo确实经常被调用,并且对每个小数据集只运行approxfun一次,那么您最好使用approx并传递估计的数据。如果同一数据真的被多次调用,你可能需要重新思考原因。在我看来,这里没有足够的上下文。这可能不容易理解,但如果我提供了goo的内部结构,它会让我不再关注我所担心的内容。函数goo接收大量数据并构建一个函数和参数,这些函数和参数将被多次使用。goo将被一次又一次地调用,以填充许多函数/参数。将根据MC的要求调用所有这些函数/参数,以估计系统的各种特性。我目前正在跟踪内存使用情况,但我担心,当我将其放大时,可能会有一些环境/语法问题困扰着我。在上面的评论中没有空间,所以……正如您所想象的,在goo生成了许多不同的函数/参数之后,我必须管理这一堆。这带来了一些我还没有问过的其他问题。这就是函数如何包含在glm对象中。例如,glmdl$family$linkinv这就是函数如何包含在glm对象中。例如,glmdl$family$linkinvItem 1,这是一个我缩短的示例,重点是传递/调用函数。函数和其他返回值都是大量内部计算的结果。第2项,如果我使用goodf$approxx与上面的相比,它会减慢速度,还是改善/恶化环境问题?第三项,我同意。事实上,这就是为什么构建真正的goo是为了提供函数/参数,这样构建函数/参数的次数就少了。在MC运行期间,函数/参数只是被多次使用,而不是多次重建。@使用goodf$approxx而不是goodf[[1]]的bill可能会更慢,因为R将需要进行哈希查找而不是位置访问,但我想差异可以忽略不计,值得可读。我也喜欢Aaron的建议,即返回一个函数并附加其调用者将需要的任何其他数据作为属性。函数和其他返回值都是大量内部计算的结果。第2项,如果我使用goodf$approxx与上面的相比,它会减慢速度,还是改善/恶化环境问题?第三项,我同意。事实上,这就是为什么构建真正的goo是为了提供函数/参数,这样构建函数/参数的次数就少了。在MC运行期间,函数/参数只是被多次使用,而不是多次重建。@使用goodf$approxx而不是goodf[[1]]的bill可能会更慢,因为R将需要进行哈希查找而不是位置访问,但我想差异可以忽略不计,值得可读。我也喜欢Aaron的建议,返回一个函数,并附加它的调用者将需要的任何其他数据作为属性。它一开始会占用更多内存,函数生成可能会或不会运行得稍慢一些……我们将拭目以待,但它允许我将一些复杂性转移到如何使用与plot.goo函数类似的结果上。另外,将类同时设置为goo和data.frame确实可以使这一点变得清晰。如果我扩展到
类,它可能有助于管理最后一堆函数。谢谢。我一直在玩弄你的解决方案。它一开始会占用更多内存,函数生成可能会或不会运行得稍慢一些……我们将拭目以待,但它允许我将一些复杂性转移到如何使用与plot.goo函数类似的结果上。另外,将类同时设置为goo和data.frame确实可以使这一点变得清晰。而且,如果我扩展该类,它可能有助于管理最后一堆函数。谢谢