0

可重现和简化的示例来解释我的核心问题

我从一个以向量作为参数的函数开始,比如: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,到目前为止一切顺利。

现在出于绘图目的,我使用要绘制的数据构建一个数据框,如下所示:

  1. 创建函数参数值:mydf <- data.frame(a=1:3, b=2:4).
  2. 使用 将函数值添加到新列中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作为列ab数据框的并集的向量参数,即:c(mydf[["a"]], mydf[["b"]]). 因此,fVec做了它被编程做的事情,即评估前两个元素的乘积,因此返回1*2=2所有行。

到目前为止,我能想出的解决这一挑战的最佳解决方案是使用以下方法:transformapply

cbind(mydf, v=apply(mydf, 1, function(row) fIndirect(row["a"], row["b"])))

问题:为什么transform将两个数据框列都传递给fVecthroughfIndirect而不是与调用它时的行为方式相同,fDirect在那里它一次评估函数一行?是 R 的错误还是我误解了 R 工作方式的基本原理,比如关于范围界定和/或参数转换?

上下文

本节解释了为什么我遵循这样的过程,也许有人可以指出一种更好的架构方法。

我有一个相当复杂的目标函数,我试图优化(即fVec角色)。为了方便起见,这个函数有可变数量的参数作为命名向量参数传入,我使用这个函数的各种方式,特别是使用 BBoptim 优化器,它期望一个向量作为目标函数的参数。

在变量参数的数量为 1 或 2 的某些情况下,我想绘制我的目标函数(我plot在 1-dim 情况下使用;我在 2-dim 情况下使用levelplotwireframefrom lattice 包)。

因此,我构建了一个带有显式参数(即fIndirect角色)的临时函数,以便于将要绘制的数据构建到数据框(即mydf角色)中。由于我的目标函数相对复杂,并且我需要一个带有向量参数的版本,我希望fIndirect通过调用我的原始目标函数来实现我的临时函数fVec

谁能提出比我在上面的简化示例中展示的过程更好的方法来实现相同的目标?

4

1 回答 1

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))调用该函数,即对于每个调用都带有一对标量的每个行索引。相反,我了解到数据框中的新列是通过将函数的矢量化形式调用为. 我在自学 R 时错过了这种基本的操作模式!fctmydffct(mydf[i, "a"], mydf[i, "b"])ivfct(mydf[["a"]], mydf[["b"]])

fIndirect因此,支持矢量化操作的正确实现可能类似于:

fIndirect <- function(a, b)
  vapply(1:length(a), function(row) fVec(c(a[row], b[row])), FUN.VALUE=1)

最重要的是,在实现函数时,请确保通过函数实现中循环遍历向量元素来支持向量参数!

关于我的上下文中的整个过程,我认为这很好。如果不需要自动化流程,作为在 R 中编写流程的替代方案,我想可以使用一些UI交互包(如Rcmdr.

我希望我所学到的细节可能对某人有用。

于 2013-04-16T15:48:06.680 回答