I have estimated a nested logit using the command mlogit()
from the R package mlogit
. The output is in the form of a list with 17 elements. If I run summary()
on the output, I get a table with the estimated coefficients and their respective standard errors. However, I cannot find such standard errors in the output of the mlogit()
command (the list with 17 elements). Am I missing where it is? Below I provide a non-reproducible example of the kind of code I am running, as well as the list of elements in the output.
My guess is that maybe the command summary()
is somehow calculating the standard errors for the estimated coefficients. Given the coefficients are estimated by mlogit()
using Maximum Likelihood, I am guessing these standard errors come from calculating the inverse of the Fischer information matrix. However, I am unsure how to do so given the output I have from the mlogit()
command. I will be thankful if anyone could help me with this.
Thanks in advance for your help!
CODE EXAMPLE:
library(dfidx)
library(mlogit)
ml_data <- data %>% dfidx(idx = c("id", "alternative"))
model_output <- mlogit(choice ~ regresor1 + regresor2,
data = ml_data,
reflevel = "alt1",
nests = list(nest1 = c("alt2", "alt3", "alt4"),
nest2 = c("alt1")),
un.nest.el = FALSE, constPar = c("iv:nest2" = 1))
summary(model_output)
OUTPUT FROM mlogit()
:
More information available here: Rdocumentation (though my list has 17 elements and the documentation only describes 13 of them)
Your example isn't reproducible, but we can run the example from ?mlogit
:
library(mlogit)
data("Fishing", package = "mlogit")
Fish <- dfidx(Fishing, varying = 2:9, shape = "wide", choice = "mode")
model <- mlogit(mode ~ price + catch, data = Fish)
This results in
model
#>
#> Call:
#> mlogit(formula = mode ~ price + catch, data = Fish, method = "nr")
#>
#> Coefficients:
#> (Intercept):boat (Intercept):charter (Intercept):pier
#> 0.87137 1.49889 0.30706
#> price catch
#> -0.02479 0.37717
Notice that the class of the model
object is "mlogit"
:
class(model)
#> [1] "mlogit"
In R, the summary
function is an S3 generic, and when we call summary(model)
, it actually calls the mlogit:::summary.mlogit
function:
summary(model)
#>
#> Call:
#> mlogit(formula = mode ~ price + catch, data = Fish, method = "nr")
#>
#> Frequencies of alternatives:choice
#> beach boat charter pier
#> 0.11337 0.35364 0.38240 0.15059
#>
#> nr method
#> 7 iterations, 0h:0m:0s
#> g'(-H)^-1g = 6.22E-06
#> successive function values within tolerance limits
#>
#> Coefficients :
#> Estimate Std. Error z-value Pr(>|z|)
#> (Intercept):boat 0.8713749 0.1140428 7.6408 2.154e-14 ***
#> (Intercept):charter 1.4988884 0.1329328 11.2755 < 2.2e-16 ***
#> (Intercept):pier 0.3070552 0.1145738 2.6800 0.0073627 **
#> price -0.0247896 0.0017044 -14.5444 < 2.2e-16 ***
#> catch 0.3771689 0.1099707 3.4297 0.0006042 ***
#> ---
#> Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
#>
#> Log-Likelihood: -1230.8
#> McFadden R^2: 0.17823
#> Likelihood ratio test : chisq = 533.88 (p.value = < 2.22e-16)
This doesn't simply print a summary to the screen - it actually does further calculations that produce an object of class "summary.mlogit"
. We can see this by storing the object and examining it:
model_summary <- summary(model)
class(model_summary)
#> [1] "summary.mlogit" "mlogit"
We will see that it contains different data members than model
does:
names(model_summary)
#> [1] "coefficients" "logLik" "gradient" "hessian"
#> [5] "est.stat" "fitted.values" "probabilities" "linpred"
#> [9] "indpar" "residuals" "omega" "rpar"
#> [13] "nests" "model" "freq" "formula"
#> [17] "call" "CoefTable" "lratio" "mfR2"
One of these, the member CoefTable
is the data table printed in the summary:
model_summary$CoefTable
#> Estimate Std. Error z-value Pr(>|z|)
#> (Intercept):boat 0.87137491 0.114042831 7.640769 2.153833e-14
#> (Intercept):charter 1.49888838 0.132932796 11.275535 0.000000e+00
#> (Intercept):pier 0.30705525 0.114573796 2.679978 7.362701e-03
#> price -0.02478955 0.001704403 -14.544420 0.000000e+00
#> catch 0.37716885 0.109970659 3.429723 6.041986e-04
If we don't want to look through all the members of an object to find the summary table, we can always just try the generic S3 coef
, to see if the authors have defined a method. It turns out they have:
coef(model_summary)
#> Estimate Std. Error z-value Pr(>|z|)
#> (Intercept):boat 0.87137491 0.114042831 7.640769 2.153833e-14
#> (Intercept):charter 1.49888838 0.132932796 11.275535 0.000000e+00
#> (Intercept):pier 0.30705525 0.114573796 2.679978 7.362701e-03
#> price -0.02478955 0.001704403 -14.544420 0.000000e+00
#> catch 0.37716885 0.109970659 3.429723 6.041986e-04
It seems that this is what you are looking for. However, you mention a variance-covariance matrix in your question, which is a different concept from the coefficient table. If you genuinely want the variance-covariance matrix, there is a vcov
method that you can use on your model too:
vcov(model)
#> (Intercept):boat (Intercept):charter (Intercept):pier
#> (Intercept):boat 1.300577e-02 1.025681e-02 7.519846e-03
#> (Intercept):charter 1.025681e-02 1.767113e-02 7.145189e-03
#> (Intercept):pier 7.519846e-03 7.145189e-03 1.312715e-02
#> price -1.807016e-06 -9.194307e-05 8.030833e-07
#> catch 7.717477e-04 -5.247810e-03 7.401401e-04
#> price catch
#> (Intercept):boat -1.807016e-06 7.717477e-04
#> (Intercept):charter -9.194307e-05 -5.247810e-03
#> (Intercept):pier 8.030833e-07 7.401401e-04
#> price 2.904989e-06 1.010511e-05
#> catch 1.010511e-05 1.209355e-02
Created on 2023-07-07 with reprex v2.0.2