可重复和简化的示例来解释我的核心问题 :
我从一个以向量作为参数的函数开始,例如: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
到fIndirect
,而不是像使用fDirect
一样调用它时的行为,其中它在一行中评估函数的一行时间?这是一个R错误还是我误解了R的工作原理,可能是关于范围界定和/或论证投射的事情?
的上下文 :
本节解释了为什么我遵循这样一个过程,也许有人可以指出一种更好的方法来构建它。
我有一个相当复杂的目标函数,我尝试优化(即fVec
角色)。这个函数有一个可变数量的参数作为命名向量参数传入,以方便我使用此函数的各种方式,特别是使用期望向量作为目标函数的参数的BBoptim优化器。
在某些情况下,变量参数的数量为1或2,我想绘制我的目标函数(我在1-dim情况下使用plot
;我使用levelplot
和{{1} }来自2-dim情况下的网格包。)
然后,我构建了一个带有显式参数(即wireframe
角色)的临时函数,以便于构建我想要绘制成数据帧的数据(即fIndirect
角色)。由于我的目标函数相对复杂,我需要一个带矢量参数的版本,我希望通过调用原始目标函数mydf
来实现我的临时函数fIndirect
。
任何人都可以提出一个更好的方法来实现相同的目标,而不是我在上面的简化示例中展示的过程吗?
答案 0 :(得分:0)
所以我可以将这个问题标记为已回答,对Joran表示赞赏,关键问题不在transform
;问题是fIndirect
不支持矢量化操作。
fDirect
带有支持向量化操作的向量参数:
fDirect(1:3,2:4)
[1] 2 6 12
fIndirect
具有相同的向量参数不支持向量化操作:
fIndirect(1:3,2:4)
[1] 2
它有意义fIndirect(1:3,2:4) = fVec(c(1:3,2:4))
,这是前两个元素的乘积。
我的误解是认为transform(mydf, v=fct(a, b))
会在数据框fct
的每一行调用函数mydf
,即每行索引fct(mydf[i, "a"], mydf[i, "b"])
i
每次调用都使用一对标量。我学会了通过将函数的矢量化形式调用为v
来生成数据框中的新列fct(mydf[["a"]], mydf[["b"]])
。在我自学R的过程中,我错过了这种基本的操作模式。
因此,fIndirect
正确实现以支持矢量化操作可能类似于:
fIndirect <- function(a, b)
vapply(1:length(a), function(row) fVec(c(a[row], b[row])), FUN.VALUE=1)
底线,在实现函数时,确保通过循环遍历向量元素来支持向量参数,因为在函数实现中!
关于我的上下文中的整个过程,我想它没关系。如果不需要自动化该过程,作为R中的过程的替代代码,我想也许可以探索并使用诸如Rcmdr
之类的UI交互式包来绘制数据。
我希望我学到的东西的细节对某人有用。