问题
I don't understand why the below two gam models produce different results. The only difference is in one of the models I added the namespace specifier gam::
before the functions gam
and s
.
I want to do this because I am exploring the differences between running the gam function in the gam package and in the mgcv package.
library(ISLR)
library(gam)
gam.m3 <- gam::gam(wage ~ gam::s(year,4) + gam::s(age,5) + education,data=Wage)
gam.m3.orig <- gam(wage ~ s(year,4) + s(age,5) + education, data=Wage)
#Coefficients are different
coef(gam.m3)[1]; coef(gam.m3.orig)[1]
#Models are different
gam.m3$df.residual; gam.m3.orig$df.residual
Here is the output. It seems like the coefficients and degrees of freedom should not be different; in fact the two models should be exactly the same. But, they are different and I don't understand why. Any suggestions welcome, I'm kind of at a loss right now.
> library(ISLR)
> library(gam)
Loading required package: splines
Loading required package: foreach
Loaded gam 1.16
> gam.m3 <- gam::gam(wage ~ gam::s(year,4) + gam::s(age,5) + education, data=Wage)
Warning message:
In model.matrix.default(mt, mf, contrasts) :
non-list contrasts argument ignored
> gam.m3.orig <- gam(wage ~ s(year,4) + s(age,5) + education, data=Wage)
Warning message:
In model.matrix.default(mt, mf, contrasts) :
non-list contrasts argument ignored
>
> #Coefficients are different
> coef(gam.m3)[1]; coef(gam.m3.orig)[1]
(Intercept)
-2058.077
(Intercept)
-2339.364
>
> #Models are different
> gam.m3$df.residual; gam.m3.orig$df.residual
[1] 2993
[1] 2986
回答1:
gam
calls gam.fit
and gam.fit
has specific code for handling smoothers. This code only works correctly, if the model.frame's "terms" attribute has them correctly specified in its "specials" attribute. Otherwise, the smoothers are handled like any other function, which apparently gives a different result. If you want to know how exactly the smoothers are handled differently, you'll need to study the source code of gam.fit
in detail.
Basically, this shows the crucial difference between your two calls to gam
:
gam.smoothers()$slist
#[1] "s" "lo" "random"
attr(terms(wage ~ s(year,4) + s(age,5) + education,
specials = gam.smoothers()$slist), "specials")
#$s
#[1] 2 3
#
#$lo
#NULL
#
#$random
#NULL
attr(terms(wage ~ gam::s(year,4) + gam::s(age,5) + education,
specials = gam.smoothers()$slist), "specials")
#$s
#NULL
#
#$lo
#NULL
#
#$random
#NULL
Why do you need to use gam::s
? Calling gam::gam
should be sufficient to ensure that the correct smoother function is called (via the namespace lookup):
gam::gam(wage ~ s(year,4) + s(age,5) + education,data=Wage)
Edit:
OK, mgcv::s
actually masks gam::s
on the search path. One approach to solve that problem can be found there.
来源:https://stackoverflow.com/questions/56437215/namespace-specifier-on-gam-package-does-not-work