Multinomial Models for Discrete Outcomes

 

The purpose of this session is to show you how to use R's procedures for doing Multinomial Logit (MNL). Additionally, we look at Ordered Logit and Probit. Note that both STATA and LIMDEP also have “canned” procedures for conditional and nested logit. There is, to date, no canned procedure in R for doing nested logit, but there is a conditional logit procedure in the survival package. LIMDEP also has a “canned” procedure for multinomial Probit. There is an R package (MNP) which will estimate the multinomial Probit model using Markov Chain Monte Carlo methods. However, we do not demonstrate these packages in this lesson.

 

# This file uses R to compare procedures for multinomial logit and ordered probit and logit for

# data that are naturally ordered. A common mistake is to estimate naturally ordered data with MNL

# or MNP. First, we estimate a multinomial logit (MNL) for the Spector and Mazzeo data with a new

# dependent variable, LETTERS. LETTERS is coded 0=C, 1=B, 2=A. Then we reestimate the model as an

# ordered logit to compare the results.

 

# Note of caution: Strictly speaking, choice models assume that n individuals make the choices,

# and that the choices are independent. However, in this example it is the instructor making the choices,

# and the choices are obviously not independent. In order to consider this example as a "choice" model,

# we need to think of the instructor as making n independent decisions based on the students' past

# grades, achievement tests, and whether s/he received a treatment, PSI. This may not be substantively correct,

# since the instructor should merely evaluate performance based on course materials, rather

# than paying attention to the student's attributes. However, the objective is to illustrate how to

# estimate these models; # not specify an appropriate substantive model.

 

library(car)

library(stats)

 

# First, let's load the data.

Spector <- read.table("c:/users/B. Dan Wood/My Documents/My Teaching/Maximum Likelihood/Data/Letters.txt", header=TRUE)

attach(Spector)

summary(Spector)

 

# We will first estimate a multinomial logit using the Zelig library (note that GLM could also be used since

# Zelig is partially just an interface for GLM). Note that the "canned" procedures in R use GLM for

# estimating many MLE oriented models.

 

#Note: The following is to unmask Zelig's simulate function when another library claims that name.

#rm(sim)

 

library(Zelig)

mlogit.out <- zelig(as.factor(LETTERS) ~ GPA + TUCE + PSI,  model = "mlogit", data = Spector)

summary(mlogit.out)

 

# Following are some interesting values that can be extracted from the model for later use.

# The value of the log-likelihood at the maximum can be used in a likelihood ratio test for

# testin the model specification.

 

loglik <- -1/2*deviance(mlogit.out)

loglik

 

# Note that Zelig does not appear to be standardized in the way to extract certain outputs.

# With mlogit the deviance and other interesting values are extracted with e.g.,

# deviance(mlogit.out). However, in other procedures the deviance is obtained by

# mlogit.out$deviance. Note also that this is not consistent with their web site

# help system. Also, names(mlogit.out) returns a null value.

# Same for the other interesting values.

 

# Model Coefficients

 

beta <-coefficients(mlogit.out)

beta

 

# Fitted Probabilities

 

fitted.probs <- fitted.values(mlogit.out)

fitted.probs

 

# Let's get the fitted probabilities the hard way now to demonstrate how it is done.

# First create the necessary matrices.

 

x <- cbind(1,GPA,TUCE,PSI)

betamat<- matrix(coefficients(mlogit.out),4,2, byrow=T)

beta0 <- betamat[,1]

beta1 <- betamat[,2]

 

# Now calculate the probabilities

 

p2 <- 1/(1+exp(x %*% beta0)+exp(x %*% beta1))

p2

p1 <- exp(x %*% beta1)*p2

p1

p0 <- exp(x %*% beta0)*p2

p0

 

# We can also calculate the probabilities with all variables at their means the hard way.

# First, calculate the means.

xbar <- as.matrix(mean(cbind(1,Spector[2:4])))

 

# Now calculate the probabilities at the means.

p2bar <- 1/(1+exp(t(xbar) %*% beta0)+exp(t(xbar) %*% beta1))

p2bar

p1bar <- exp(t(xbar) %*% beta1)*p2bar

p1bar

p0bar <- exp(t(xbar) %*% beta0)*p2bar

p0bar

 

# Note that the preceding can be used to calculate first differences simply by replacing

# elements on xbar with interesting units. For example, we might consider moving PSI=0 to PSI=1

# to see the effect on the three probabilities.

 

xbar[4,1]=0

p2bar <- 1/(1+exp(t(xbar) %*% beta0)+exp(t(xbar) %*% beta1))

p2bar

p1bar <- exp(t(xbar) %*% beta1)*p2bar

p1bar

p0bar <- exp(t(xbar) %*% beta0)*p2bar

p0bar

 

xbar[4,1]=1

p2bar <- 1/(1+exp(t(xbar) %*% beta0)+exp(t(xbar) %*% beta1))

p2bar

p1bar <- exp(t(xbar) %*% beta1)*p2bar

p1bar

p0bar <- exp(t(xbar) %*% beta0)*p2bar

p0bar

 

# We can also allow Zelig to calculate first differences.

 

#Simulate the predicted probabilities of making an A, PSI=0, rest at mean

x.out <- setx(mlogit.out, GPA=2, PSI = 0)

s.out <- sim(mlogit.out, x = x.out, num=10000)

summary(s.out)

 

#Simulate the predicted probability of making an A, PSI=1, rest at mean

x.out <- setx(mlogit.out, GPA=3, PSI=0)

s.out <- sim(mlogit.out, x = x.out)

summary(s.out)

 

# We could just take the difference between these to get a first difference. However, Zelig

# can do this in one step.

 

# First Difference when Shifting GPA from 2 to 3 with PSI=0 and TUCE at mean

gpa.low <- setx(mlogit.out, GPA=2, PSI=0)

gpa.high <- setx(mlogit.out, GPA = 3, PSI=0)

s.out <- sim(mlogit.out, x = gpa.low, x1 = gpa.high)

summary(s.out)

plot(s.out)

 

# Now let's use Zelig to do an ordered probit and an ordered logit

 

oprobit.out <- zelig(as.factor(LETTERS) ~ GPA + TUCE + PSI,  model = "oprobit", data = Spector)

summary(oprobit.out)

 

# Simulate ordered probit first differences using PSI=0 to PSI=1

x.low <- setx(oprobit.out, PSI=0)

x.high <- setx(oprobit.out, PSI= 1)

s.out <- sim(oprobit.out, x = x.low, x1 = x.high)

summary(s.out)

plot(s.out)

 

ologit.out <- zelig(as.factor(LETTERS) ~ GPA + TUCE + PSI,  model = "ologit", data = Spector)

summary(ologit.out)

 

# Simulate ordered logit first differences using PSI=0 to PSI=1

x.low <- setx(ologit.out, PSI=0)

x.high <- setx(ologit.out, PSI= 1)

s.out <- sim(ologit.out, x = x.low, x1 = x.high)

summary(s.out)

plot(s.out)

 

# Note that there are no "canned" procedures in R for calculating marginal effects or

# testing assumptions about IIA. See Greene 2003 for details that could be programmed.

 

# Also, there are no "canned" nested logit procedures, or an MNP procedure such as in

# LIMDEP. There is a package for doing MNP with MCMC techniques. However, I have not

# explored its utility for this lesson. Therefore, unless you are willing to do some

# programming work it is probably better to use STATA or LIMDEP when these are needed.