2017-03-11 2 views
0

Je me gratte vraiment la tête ici. Je ne comprends vraiment pas ce qui se passe. C'est un MWE, mais le code et le but sont plus complexes que cela. Ainsi, le code:parzyeval ne pas trouver `C_logit_link` lors de l'utilisation de binomial dans la fonction glm

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() 
     ) 
    ) 

qui retourne: Error in family$linkfun(mustart) : object 'C_logit_link' not found ... mais ce bit de code fonctionne très bien:

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

La seule différence entre les deux est la distribution de la famille utilisée (gaussienne vs binomiale) et la variable utilisée.

Donc la question: pourquoi est-ce que lazyeval ne peut pas trouver C_logit_link?

Répondre

1

Lorsque vous appelez interp(x, *), il évalue les arguments à interpoler en x. Dans le cas de binomial(), le résultat est une structure qui représente la distribution binomiale dans un 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)) 
# . . . 

enterré à l'intérieur de cette structure est une fonction qui appelle à code C compilé, via l'objet C_logit_link. C'est un objet non exporté dans le paquet stats. Normalement tout fonctionne bien, parce que l'environnement de cette fonction est l'espace de noms des statistiques et donc il est capable de trouver C_logit_link.

Le problème ici est que l'objet que vous interpolez est une chaîne, ce qui signifie que tout ce qui y est interpolé est également forcé dans une chaîne. Cela perd l'information d'environnement nécessaire pour trouver C_logit_link.

La solution est de interp une formule à la place:

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 
+0

Huh, fascinant. Cela a réglé mon problème! Merci :) – Luke