Проблема с отложенной оценкой - функции внутри таблицы - PullRequest
0 голосов
/ 11 марта 2019

Настройка

Я буду использовать tibble () от tidyverse в этом примере для хранения функций.

Скажем, у меня есть следующий тиббл (этосписок различных функций),

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, чтобы заменить соответствующий элемент композицией изстолбцы стоимости и потока):

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
}

Вопрос

Что я не могу найти, так это почему?Я предполагаю, что ограничивающую характеристику я не понимаю?

Просто для интереса читателей, вариант использования этого подхода представляет сеть с потоками и затратами.И желая делать операции с ними.

1 Ответ

1 голос
/ 11 марта 2019

Это проблема с ленивой оценкой, а не с областью видимости.Проблема в том, что функция 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)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...