懒惰的评估问题 - 在一个tibble中的功能

问题描述 投票:0回答:1

设置

我将在这个例子中使用来自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
}

问题

我找不到的是为什么会这样?我假设一个我不明白的范围特征?

仅为了读者的兴趣,这种方法的用例代表了具有流量和成本的网络。并希望与他们合作。

r
1个回答
1
投票

这是懒惰评估而不是范围界定的问题。问题是Composite函数从不评估fg,它只是创建一个函数,将这些名称作为其身体的一部分。在第一次通话之前,它们的价值不固定。很难弄清楚实际值来解释-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)
© www.soinside.com 2019 - 2024. All rights reserved.