设置
我将在这个例子中使用来自tidyverse的tibble()来存储函数。
说我有以下的tibble(这是一个不同的功能),
cost.matrix <- tibble(cost = c(function(x){0}, function(x){0}, function(x){NA}, function(x){x^2}, function(x){(3/2)*x}, function(x){x}),
flow = c(function(alpha,beta){(1/2)-alpha},function(alpha,beta){(1/2)-beta}, function(alpha,beta){NA}, function(alpha,beta){alpha}, function(alpha,beta){beta},
function(alpha, beta){1-alpha-beta}))
例如,
cost.matrix$cost
# and
cost.matrix$flow
将列出所有功能。
现在我想创建一个新列,它组成了流程和成本函数,例如,
function(x){x^2}
# and
function(alpha, beta){1-alpha-beta}
# The new function will be
function(alpha, beta){(1-alpha-beta)^2}
所以要做到这一点,我使用一个简单的for循环(如果有人有更好的建议,请让我知道,无法矢量化以下组合函数),并在每一行使用此组合函数:
Composite <- function(f,g) function(...) f(g(...))
所以现在我们的代码如下所示(我们创建一个新列,然后使用for循环用cost和flow列中的组合替换相应的元素):
data <- cost.matrix %>%
mutate(cost.flow.comp = cost)
for (i in 1:nrow(data)){
a <- data$cost[[i]]
b <- data$flow[[i]]
want <- Composite(a,b)
data$cost.flow.comp[[i]] <- want
}
问题
如果我们运行以下代码,我们现在应该得到25:
data$cost.flow.comp[[4]](5,2)
因为相关的功能是:
function(x){x^2}
# and
function(alpha, beta){alpha}
但是我们得到-6,因为cost.flow.comp列中的每个元素实际上都已分配给以下函数的组合:
function(x){x}
function(alpha,beta){1-alpha-beta}
解决方案我找到了解决这个问题的方法,并且每次在for循环中调用函数后都要调用它。例如(我们在为其分配组合后调用want函数):
data <- cost.matrix %>%
mutate(cost.flow.comp = cost)
for (i in 1:nrow(data)){
a <- data$cost[[i]]
b <- data$flow[[i]]
want <- Composite(a,b)
want(1,1)
data$cost.flow.comp[[i]] <- want
}
问题
我找不到的是为什么会这样?我假设一个我不明白的范围特征?
仅为了读者的兴趣,这种方法的用例代表了具有流量和成本的网络。并希望与他们合作。
这是懒惰评估而不是范围界定的问题。问题是Composite
函数从不评估f
或g
,它只是创建一个函数,将这些名称作为其身体的一部分。在第一次通话之前,它们的价值不固定。很难弄清楚实际值来解释-6的位置,但解决方法很简单:将Composite
更改为
Composite <- function(f, g) {
force(f)
force(g)
function(...) f(g(...))
}
然后你的原始版本工作。
> data <- cost.matrix %>%
+ mutate(cost.flow.comp = cost)
> for (i in 1:nrow(data)){
+ a <- data$cost[[i]]
+ b <- data$flow[[i]]
+ want <- Composite(a,b)
+ data$cost.flow.comp[[i]] <- want
+ }
> data$cost.flow.comp[[4]](5,2)
[1] 25
顺便说一句,我怀疑有更多功能的方法来创建cost.flow.comp
列,但我不知道tidyverse
的东西。我是用mapply
做的,即
data$new.column <- mapply(Composite, data$cost, data$flow)