可重现和简化的示例来解释我的核心问题:
我从一个以向量作为参数的函数开始,比如:fVec <- function(v) v[1]*v[2]
.
出于比较目的,使用显式参数来表达相同功能的直接方式是:fDirect <- function(a, b) a*b
.
在我的用例中,我想用fDirect
上面的显式参数构建一个函数,但通过调用初始函数来实现它fVec
。所以为了这个目的,我定义了:fIndirect <- function(a, b) fVec(c(a, b))
. (我在下面解释为什么我想做这样的事情显然没有任何意义!)
正如预期的那样,fVec(c(2, 3))
,fDirect(2, 3)
和fIndirect(2, 3)
返回 6,到目前为止一切顺利。
现在出于绘图目的,我使用要绘制的数据构建一个数据框,如下所示:
- 创建函数参数值:
mydf <- data.frame(a=1:3, b=2:4)
. - 使用 将函数值添加到新列中
transform
。
使用fDirect
,transform(mydf, v=fDirect(a, b))
确实按预期工作,它返回:
> transform(mydf, v=fDirect(a, b))
a b v
1 1 2 2
2 2 3 6
3 3 4 12
但是,使用fIndirect
,它不会返回所需的函数值:
> transform(mydf, v=fIndirect(a, b))
a b v
1 1 2 2
2 2 3 2
3 3 4 2
在调试中,我意识到使用fIndirect
,transform
传递给fVec
作为列a
和b
数据框的并集的向量参数,即:c(mydf[["a"]], mydf[["b"]])
. 因此,fVec
做了它被编程做的事情,即评估前两个元素的乘积,因此返回1*2=2
所有行。
到目前为止,我能想出的解决这一挑战的最佳解决方案是使用以下方法:transform
apply
cbind(mydf, v=apply(mydf, 1, function(row) fIndirect(row["a"], row["b"])))
问题:为什么transform
将两个数据框列都传递给fVec
throughfIndirect
而不是与调用它时的行为方式相同,fDirect
在那里它一次评估函数一行?是 R 的错误还是我误解了 R 工作方式的基本原理,比如关于范围界定和/或参数转换?
上下文:
本节解释了为什么我遵循这样的过程,也许有人可以指出一种更好的架构方法。
我有一个相当复杂的目标函数,我试图优化(即fVec
角色)。为了方便起见,这个函数有可变数量的参数作为命名向量参数传入,我使用这个函数的各种方式,特别是使用 BBoptim 优化器,它期望一个向量作为目标函数的参数。
在变量参数的数量为 1 或 2 的某些情况下,我想绘制我的目标函数(我plot
在 1-dim 情况下使用;我在 2-dim 情况下使用levelplot
和wireframe
from lattice 包)。
因此,我构建了一个带有显式参数(即fIndirect
角色)的临时函数,以便于将要绘制的数据构建到数据框(即mydf
角色)中。由于我的目标函数相对复杂,并且我需要一个带有向量参数的版本,我希望fIndirect
通过调用我的原始目标函数来实现我的临时函数fVec
。
谁能提出比我在上面的简化示例中展示的过程更好的方法来实现相同的目标?