lazyeval не находит `C_logit_link` при использовании бинома в функции glm

Я действительно чешу голову здесь. Я действительно не понимаю, что происходит. Это MWE, но реальный код и цель более сложны, чем эта. Итак, код:

library(dplyr)
ds <- mutate(iris, Species = as.numeric(Species == 'setosa'))

ds %>%
    do_(
        .dots = lazyeval::interp(
            "broom::tidy(stats::glm(form, data = ., family = distr))",
            form = Species ~ Sepal.Length,
            distr = binomial()
        )
    )

Который возвращает: Error in family$linkfun(mustart) : object 'C_logit_link' not found... но этот код работает нормально:

ds %>%
    do_(
        .dots = lazyeval::interp(
            "broom::tidy(stats::glm(form, data = ., family = distr))",
            form = Sepal.Width ~ Sepal.Length,
            distr = gaussian()
        )
    )

Единственное различие между ними заключается в используемом распределении по семействам (гауссовский и биномиальный) и используемой переменной.

Итак, вопрос: почему Лазеваль не может найти C_logit_link?

1 ответ

Решение

Когда вы звоните interp(x, *)он оценивает аргументы, которые должны быть интерполированы в x, В случае binomial()В результате получается структура, представляющая биномиальное распределение в GLM.

interp(~x, x=binomial())

#~list(family = "binomial", link = "logit", linkfun = function (mu) 
#.Call(C_logit_link, mu), linkinv = function (eta) 
#.Call(C_logit_linkinv, eta), variance = function (mu) 
#mu * (1 - mu), dev.resids = function (y, mu, wt) 
#.Call(C_binomial_dev_resids, y, mu, wt), aic = function (y, n, 
#    mu, wt, dev) 
#{
#    m <- if (any(n > 1)) 
#    . . .

Внутри этой структуры находится функция, которая вызывает к скомпилированному коду C через объект C_logit_link, Это не экспортируемый объект в пакете статистики. Обычно все работает нормально, потому что среда этой функции - это пространство имен stats, и поэтому она может найти C_logit_link,

Проблема здесь в том, что объект, который вы интерполируете, является строкой, что означает, что все, что интерполируется в него, также преобразуется в строку. Это теряет информацию об окружающей среде, необходимую для поиска C_logit_link,

Решение состоит в том, чтобы вместо этого интерпретировать формулу:

library(dplyr)
ds <- mutate(iris, Species = as.numeric(Species == 'setosa'))

ds %>%
    do_(
        .dots = lazyeval::interp(
            ~broom::tidy(stats::glm(form, data = ., family = distr)),  # formula
            form = Species ~ Sepal.Length,
            distr = binomial()
        )
    )

#          term  estimate std.error statistic      p.value
#1  (Intercept) 27.828521 4.8275611  5.764509 8.189574e-09
#2 Sepal.Length -5.175698 0.8933984 -5.793270 6.902910e-09
Другие вопросы по тегам