r - 惰性求值问题 - tibble 中的函数
问题描述
设置
在此示例中,我将使用 tidyverse 中的 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
or 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)
推荐阅读
- swift - 在 SwiftUI Picker 列表上使用部分标题?
- r - 如何在每个 selectInput 选择中停止 dropdownButton 关闭
- lighthouse - Lighthouse 没有计算出正确的结果
- javascript - 无法更新同一对象内有另一个数组的对象数组
- c# - 将处理程序委托为瞬态或单例
- reactjs - ReactJS 测试中的“TypeError:未定义不是函数”(useContext() 未定义?)
- java - 使用 RunScript 加载 SQL 脚本文件
- python-3.x - 从两个子类调用时仅实例化一次父类
- javascript - 更改后如何重新渲染状态
- swift - 通过投射我自己的 collectionViewCell 导致 Xcode Swift 错误