Quite often the outcome of interest (aka our dependent variable) may be an ordinal response. The most typical examples include survey questions where, for example, the respondent is asked: “How concerned are you about global warming?” and he/she responds with one of the following options – “not at all”, “somewhat”, “a great deal”. Note that these responses have a hierarchy of concern that goes from the lowest level (not at all concerned) to the highest level (a great deal).
Of course, the number of ordinal response categories may not be three, they could be any number – four, five, six, seven, and more. In the past analysts treated these responses as interval-level measures. Specifically, let us say the lowest level was coded 0 and the highest level was coded 2, then \(y = 0, 1, 2\) with \(0\) representing not at all concerned; \(1\) representing somewhat concerned and \(2\) representing a great deal of concern. In a linear regression model the assumption is that the difference between 0 and 1 is the same as that between a 1 and 2 but here the numbers represent categories not numeric measurements! If we ignore this important quality of the outcome variable and proceed with the usual linear regression model we end up with biased and misleading results.
Once more we assume some underlying variable that is latent and ranges from \(-\infty\) to \(+\infty\) and can be modeled as a function of some independent variables:
\[y^{*}_{i} = x_{i}\beta + e_{i}\]
Assume the outcome of interest is subjects’ responses to the question: ‘A working mother can establish just as warm and secure a relationship with her children as a mother who does not work.’ Response categories are:
Assume too that the latent variable underlying these responses is the subjects’ degree of support for this statement about working mothers. We can then write the ordinal model as follows:
\[y=\begin{cases} 1 = SA & \text{if } \left(\tau_{0} = -\infty \right) \leq y^{*}_{i} < \tau_{1} \\ 2 = D & \text{if } \tau_{1} \leq y^{*}_{i} < \tau_{2} \\ 3 = A & \text{if } \tau_{2} \leq y^{*}_{i} < \tau_{3} \\ 4 = SA & \text{if } \tau_{3} \leq y^{*}_{i} < \left( \tau_{4} = +\infty \right) \end{cases}\]
In simple terms what this means is that we observe a particular ordinal response depending upon what part of the latent distribution an individual is in. We see the next ‘higher’ response only when the individual then crosses that particular threshold (also referred to as cutpoint). Obviously the goal becomes to find these cutpoints as a function of some independent variables available to us.
Once again, just as with the binary logit and probit models here too we need to assume something about the variance of the residuals. The logit and the probit are two commonly employed options, with the choice between the two depending upon model fit, convenience, and our ultimate goal (for example, if we are also modeling some sort of a second-stage in the outcome process then the probit is easier to work with).
The basic model assumes proportional odds – that a unit change in any independent variable has the same impact on moving from the Strongly Disagree to Disagree as it does on moving from Disagree to Agree and also on moving from Agree to Strongly Agree. This is an assumption built into the model and is often tested because it is a strong assumption. Any independent variable may have different impacts depending on the response level. This would have to be empirically verified of course and there are some tests for checking to see if the data meet the proportional odds assumption or whether the data violate this assumption. We’ll look at this test but note that these tests have been criticized for “having a tendency to reject the null hypothesis (that the sets of coefficients are the same), and hence, indicate that there the parallel slopes assumption does not hold, in cases where the assumption does hold”.
Diagnostics for these model are impossible to run so don’t go looking for anything along the lines of what we have used thus far. The only checks seem to be with the maximum likelihood, to see if the model converges and how fast, and how reliably.
There are some statistics we can continue to use. These include the pseudo-\(R^2\) for example, the AIC, the BIC, and the usual likelihood ratio tests to see if including the independent variables improves upon the model without any independent variables. We can also test for nested models.
Be sure to install the rms
package before you run the code below.
library(rms)
library(foreign)
ordwarm2 = read.dta("http://www.ats.ucla.edu/stat/stata/examples/long/ordwarm2.dta")
names(ordwarm2)
## [1] "warm" "yr89" "male" "white" "age" "ed" "prst"
## [8] "warmlt2" "warmlt3" "warmlt4"
summary(ordwarm2)
## warm yr89 male white age
## SD:297 1977:1379 Women:1227 White : 283 Min. :18.00
## D :723 1989: 914 Men :1066 Not Whit:2010 1st Qu.:31.00
## A :856 Median :42.00
## SA:417 Mean :44.94
## 3rd Qu.:58.00
## Max. :89.00
## ed prst warmlt2 warmlt3 warmlt4
## Min. : 0.00 Min. :12.00 D,A,SA:1996 A,SA:1273 SA : 417
## 1st Qu.:11.00 1st Qu.:30.00 SD : 297 D,SD:1020 A,D,SD:1876
## Median :12.00 Median :37.00
## Mean :12.22 Mean :39.59
## 3rd Qu.:14.00 3rd Qu.:50.00
## Max. :20.00 Max. :82.00
These are data from the General Social Survey (1977 and 1989) and include the following variables:
We’ll start with the ordinal logit model and estimate the following model in particular for the 1977 responses:
\[warm = male + white + age + ed + prst\]
ol.1 = orm(warm ~ yr89 + male + white + age + ed + prst, data = ordwarm2)
ol.1
##
## Logistic (Proportional Odds) Ordinal Regression Model
##
## orm(formula = warm ~ yr89 + male + white + age + ed + prst, data = ordwarm2)
## Frequencies of Responses
##
## SD D A SA
## 297 723 856 417
##
## Model Likelihood Discrimination Rank Discrim.
## Ratio Test Indexes Indexes
## Obs 2293 LR chi2 301.72 R2 0.133 rho 0.349
## Unique Y 4 d.f. 6 g 0.785
## Median Y 3 Pr(> chi2) <0.0001 gr 2.193
## max |deriv| 0.002 Score chi2 301.80 |Pr(Y>=median)-0.5| 0.139
## Pr(> chi2) <0.0001
##
## Coef S.E. Wald Z Pr(>|Z|)
## y>=D 2.4654 0.2389 10.32 <0.0001
## y>=A 0.6309 0.2333 2.70 0.0068
## y>=SA -1.2619 0.2340 -5.39 <0.0001
## yr89=1989 0.5239 0.0799 6.56 <0.0001
## male=Men -0.7333 0.0785 -9.34 <0.0001
## white=Not Whit -0.3912 0.1184 -3.30 0.0010
## age -0.0217 0.0025 -8.78 <0.0001
## ed 0.0672 0.0160 4.20 <0.0001
## prst 0.0061 0.0033 1.84 0.0652
op.1 = orm(warm ~ yr89 + male + white + age + ed + prst, data = ordwarm2, family=probit)
op.1
##
## Probit Ordinal Regression Model
##
## orm(formula = warm ~ yr89 + male + white + age + ed + prst, data = ordwarm2,
## family = probit)
## Frequencies of Responses
##
## SD D A SA
## 297 723 856 417
##
## Model Likelihood Discrimination Rank Discrim.
## Ratio Test Indexes Indexes
## Obs 2293 LR chi2 294.32 R2 0.130 rho 0.349
## Unique Y 4 d.f. 6 g 0.451
## Median Y 3 Pr(> chi2) <0.0001 gr 1.571
## max |deriv| 4e-06 Score chi2 289.84 |Pr(Y>=median)-0.5| 0.131
## Pr(> chi2) <0.0001
##
## Coef S.E. Wald Z Pr(>|Z|)
## y>=D 1.4286 0.1388 10.29 <0.0001
## y>=A 0.3606 0.1369 2.63 0.0085
## y>=SA -0.7682 0.1371 -5.60 <0.0001
## yr89=1989 0.3188 0.0469 6.80 <0.0001
## male=Men -0.4170 0.0455 -9.16 <0.0001
## white=Not Whit -0.2265 0.0695 -3.26 0.0011
## age -0.0122 0.0014 -8.47 <0.0001
## ed 0.0387 0.0093 4.15 <0.0001
## prst 0.0033 0.0019 1.71 0.0881
AIC(ol.1); BIC(ol.1)
## [1] 5707.825
## [1] 5759.463
AIC(op.1); BIC(op.1)
## [1] 5715.222
## [1] 5766.861
exp(coef(ol.1))
## y>=D y>=A y>=SA yr89=1989 male=Men
## 11.7676866 1.8793063 0.2831293 1.6886031 0.4803221
## white=Not Whit age ed prst
## 0.6762727 0.9785675 1.0694801 1.0060912
Note the estimates generated.
The reference category is the first threshold (for a response of Strongly Disagree) and so you see the thresholds for \(y \geq D\), \(y \geq A\), and \(y \geq SA\)
Virtually everything except prst is statistically significant, and this is true in both the logit and the probit specifications.
The pseudo-\(R^2\) is 0.133 for the logit and 0.130 for the probit specifications, respectively.
The Pr(> chi2) is the p-value of the likelihood-ratio test comparing the model with all independent variables you have specified against a model with no independent variables. If the p-value indicates statistical significance then it means the model is an improvement over the NULL model (i.e., the model with no independent variables).
The AIC and BIC suggest the logit specification is slightly better than the probit specification
The odds-ratios are proportional odds-ratios in that they indicate, for example, that the odds of Men responding Disagree, Agree, or Strongly Agree are 0.48 those of Women responding similarly, holding all else constant. Likewise, the odds of a Non-White respondent responding Disagree or Agree or Strongly Agree are lower by 0.67 as compared to a White respondent, holding all else constant.
Continuous variables are trickier to work with in terms of odds-ratios because the odds are not constant across the range of the independent variable, much as was the case in the binary logit and probit models. This is where predicted probabilities come in handy (see below).
There is no easy way to calculate the pseudo\(R^2\) and the percent correctly predicted by the rms package. Other packages – polr
and VGAM
do these calculations but the rms package is better. Plus there is disagreement about the value of these two statistics in terms of assessing model fit.
Interpretation of the estimates is complicated but one way to interpret the estimates is by calculating predicted probabilities for specific profiles of individuals, and by plotting these probabilities as well. Note: visreg
will be useless here since it is not designed to work with these models.
As usual we can start by creating a profile of two individuals who are similar on all dimensions except one independent variable. Let us look at the difference between men and women.
summary(ordwarm2)
## warm yr89 male white age
## SD:297 1977:1379 Women:1227 White : 283 Min. :18.00
## D :723 1989: 914 Men :1066 Not Whit:2010 1st Qu.:31.00
## A :856 Median :42.00
## SA:417 Mean :44.94
## 3rd Qu.:58.00
## Max. :89.00
## ed prst warmlt2 warmlt3 warmlt4
## Min. : 0.00 Min. :12.00 D,A,SA:1996 A,SA:1273 SA : 417
## 1st Qu.:11.00 1st Qu.:30.00 SD : 297 D,SD:1020 A,D,SD:1876
## Median :12.00 Median :37.00
## Mean :12.22 Mean :39.59
## 3rd Qu.:14.00 3rd Qu.:50.00
## Max. :20.00 Max. :82.00
newdata.a = data.frame(yr89="1989", male="Men", white="Not Whit", age=44.94, ed=12.22, prst=39.59)
newdata.b = data.frame(yr89="1989", male="Women", white="Not Whit", age=44.94, ed=12.22, prst=39.59)
yhat.a = predict(ol.1, newdata.a, type="fitted.ind")
yhat.b = predict(ol.1, newdata.b, type="fitted.ind")
yhat.a; yhat.b
## warm=SD warm=D warm=A warm=SA
## 0.1242893 0.3462526 0.3845099 0.1449482
## warm=SD warm=D warm=A warm=SA
## 0.06382115 0.23534594 0.43996977 0.26086314
Remember the question wording: ‘A working mother can establish just as warm and secure a relationship with her children as a mother who does not work.’
So holding all else constant, women were more likely to Strongly Disagree, Disagree, Agree, or Strongly Agree with the statement than were men.
Was this any different in 1977?
newdata.c = data.frame(yr89="1977", male="Men", white="Not Whit", age=44.94, ed=12.22, prst=39.59)
newdata.d = data.frame(yr89="1977", male="Women", white="Not Whit", age=44.94, ed=12.22, prst=39.59)
yhat.c = predict(ol.1, newdata.c, type="fitted.ind")
yhat.d = predict(ol.1, newdata.d, type="fitted.ind")
yhat.c; yhat.d
## warm=SD warm=D warm=A warm=SA
## 0.19332910 0.40678313 0.30865602 0.09123174
## warm=SD warm=D warm=A warm=SA
## 0.1032318 0.3156499 0.4082435 0.1728747
There seem to be some differences in absolute probabilities of a particular response but the general gap between Men and Women stayed the same between 1977 and 1989.
We could also ask how a woman’s age influenced her response in, say, 1977.
newdata.e = data.frame(yr89="1977", male="Women", white="Not Whit", age=seq(18, 89, by=1), ed=12.22, prst=39.59)
yhat.e = predict(ol.1, newdata.e, type="fitted.ind")
yhat.f = predict(ol.1, newdata.e, type="fitted")
Note the difference between type=“fitted.ind”
and type=“fitted”
. In many ways fited.ind would be more readily understood by most audiences.
Let us try and plot the predicted probabilities from newdata.e
plot(newdata.e$age, yhat.e[, 1], col="red", type="l", xlab="Age (in years)", ylab="Predicted Probability of Specific Response")
par(new=TRUE)
plot(newdata.e$age, yhat.e[, 2], col="blue", type="l", yaxt="no", ylab="", xaxt="no", xlab="")
par(new=TRUE)
plot(newdata.e$age, yhat.e[, 3], col="darkgreen", type="l", yaxt="no", ylab="", xaxt="no", xlab="")
par(new=TRUE)
plot(newdata.e$age, yhat.e[, 4], col="goldenrod", type="l", yaxt="no", ylab="", xaxt="no", xlab="")
text(84, 0.23, "SD", cex=0.75)
text(70, 0.25, "D", cex=0.75)
text(50, 0.25, "A", cex=0.75)
text(22, 0.23, "SA", cex=0.75)
newdata.f = data.frame(yr89="1989", male="Women", white="Not Whit", age=seq(18, 89, by=1), ed=12.22, prst=39.59)
yhat.g = predict(ol.1, newdata.f, type="fitted.ind")
yhat.h = predict(ol.1, newdata.f, type="fitted")
yhat.g = data.frame(yhat.g)
yhat.e = data.frame(yhat.e)
par(mfrow=c(1,2))
plot(newdata.f$age, yhat.g$warm.A, type="l", col="red", xlab="Age (in Years)", ylab="Probability of a Specific Response", main="GSS 1989", ylim=c(0, 0.5))
par(new=TRUE)
plot(newdata.f$age, yhat.g$warm.SA, type="l", col="green", xaxt="no", yaxt="no", xlab="", ylab="", ylim=c(0, 0.5))
par(new=TRUE)
plot(newdata.f$age, yhat.g$warm.D, type="l", col="purple", xaxt="no", yaxt="no", xlab="", ylab="", ylim=c(0, 0.5))
par(new=TRUE)
plot(newdata.f$age, yhat.g$warm.SD, type="l", col="black", xaxt="no", yaxt="no", xlab="", ylab="", ylim=c(0, 0.5))
text(80, 0.40, "A", cex=0.75)
text(20, 0.30, "SA", cex=0.75)
text(30, 0.15, "D", cex=0.75)
text(60, 0.10, "SD", cex=0.75)
plot(newdata.e$age, yhat.e$warm.A, type="l", col="red", xlab="Age (in Years)", ylab="Probability of a Specific Response", main="GSS 1977", ylim=c(0, 0.5))
par(new=TRUE)
plot(newdata.e$age, yhat.e$warm.SA, type="l", col="green", xaxt="no", yaxt="no", xlab="", ylab="", ylim=c(0, 0.5))
par(new=TRUE)
plot(newdata.e$age, yhat.e$warm.D, type="l", col="purple", xaxt="no", yaxt="no", xlab="", ylab="", ylim=c(0, 0.5))
par(new=TRUE)
plot(newdata.e$age, yhat.e$warm.SD, type="l", col="black", xaxt="no", yaxt="no", xlab="", ylab="", ylim=c(0, 0.5))
text(20, 0.47, "A", cex=0.75)
text(80, 0.12, "SA", cex=0.75)
text(80, 0.45, "D", cex=0.75)
text(30, 0.10, "SD", cex=0.75)
The VGAM
package will come in very handy here. The first thing we will have to do is to specify warm as an ordered factor (otherwise VGAM won’t work). To do this we create a second data-frame and then specify warm as an ordered factor. We can then run two models, one assuming proportional odds and the other model assuming non-proportional odds. We can then use a likelihood ratio test to compare the two. If the \(p-value\) is significant then we reject the proportional odds assumption. In many ways the model summaries will also show you if the assumption holds but these are tricky models so one should not reject (or fail to reject) the proportional odds assumption without looking into the details of this assumption and the debate surrounding how best to test it.
library(VGAM)
ordwarm2a = ordwarm2
ordwarm2a$warm = ordered(ordwarm2a$warm, levels = c("SD", "D", "A", "SA"))
vglmP = vglm(warm ~ yr89 + male + white + age + ed + prst, data = ordwarm2a, family=cumulative(parallel=TRUE, reverse=TRUE))
vglmNP = vglm(warm ~ yr89 + male + white + age + ed + prst, data = ordwarm2a, family=cumulative(parallel=FALSE, reverse=TRUE))
lrtest(vglmP, vglmNP)
## Likelihood ratio test
##
## Model 1: warm ~ yr89 + male + white + age + ed + prst
## Model 2: warm ~ yr89 + male + white + age + ed + prst
## #Df LogLik Df Chisq Pr(>Chisq)
## 1 6870 -2844.9
## 2 6858 -2820.3 -12 49.203 1.928e-06 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
summary(vglmP)
##
## Call:
## vglm(formula = warm ~ yr89 + male + white + age + ed + prst,
## family = cumulative(parallel = TRUE, reverse = TRUE), data = ordwarm2a)
##
## Pearson residuals:
## Min 1Q Median 3Q Max
## logit(P[Y>=2]) -4.844 0.1531 0.2244 0.5373 1.109
## logit(P[Y>=3]) -2.872 -0.9299 0.3015 0.8573 2.525
## logit(P[Y>=4]) -1.421 -0.6085 -0.2736 -0.1611 4.939
##
## Coefficients:
## Estimate Std. Error z value Pr(>|z|)
## (Intercept):1 2.465357 0.239499 10.294 < 2e-16 ***
## (Intercept):2 0.630899 0.233775 2.699 0.00696 **
## (Intercept):3 -1.261857 0.234797 -5.374 7.69e-08 ***
## yr891989 0.523906 0.080407 6.516 7.24e-11 ***
## maleMen -0.733295 0.078526 -9.338 < 2e-16 ***
## whiteNot Whit -0.391161 0.118675 -3.296 0.00098 ***
## age -0.021665 0.002488 -8.710 < 2e-16 ***
## ed 0.067173 0.015952 4.211 2.54e-05 ***
## prst 0.006073 0.003290 1.846 0.06495 .
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Number of linear predictors: 3
##
## Names of linear predictors:
## logit(P[Y>=2]), logit(P[Y>=3]), logit(P[Y>=4])
##
## Dispersion Parameter for cumulative family: 1
##
## Residual deviance: 5689.825 on 6870 degrees of freedom
##
## Log-likelihood: -2844.912 on 6870 degrees of freedom
##
## Number of iterations: 4
##
## Exponentiated coefficients:
## yr891989 maleMen whiteNot Whit age ed
## 1.6886107 0.4803236 0.6762709 0.9785675 1.0694806
## prst
## 1.0060911
summary(vglmNP)
##
## Call:
## vglm(formula = warm ~ yr89 + male + white + age + ed + prst,
## family = cumulative(parallel = FALSE, reverse = TRUE), data = ordwarm2a)
##
## Pearson residuals:
## Min 1Q Median 3Q Max
## logit(P[Y>=2]) -4.765 0.1514 0.2249 0.4749 1.260
## logit(P[Y>=3]) -2.932 -0.8985 0.2957 0.8366 2.609
## logit(P[Y>=4]) -1.305 -0.5451 -0.2681 -0.1570 4.891
##
## Coefficients:
## Estimate Std. Error z value Pr(>|z|)
## (Intercept):1 1.856953 0.390774 4.752 2.01e-06 ***
## (Intercept):2 0.719810 0.266485 2.701 0.00691 **
## (Intercept):3 -1.002225 0.343655 -2.916 0.00354 **
## yr891989:1 0.955744 0.153174 6.240 4.39e-10 ***
## yr891989:2 0.536372 0.092002 5.830 5.54e-09 ***
## yr891989:3 0.331219 0.113159 2.927 0.00342 **
## maleMen:1 -0.300983 0.127710 -2.357 0.01843 *
## maleMen:2 -0.717994 0.089070 -8.061 7.57e-16 ***
## maleMen:3 -1.085617 0.121810 -8.912 < 2e-16 ***
## whiteNot Whit:1 -0.528730 0.226553 -2.334 0.01961 *
## whiteNot Whit:2 -0.349234 0.139250 -2.508 0.01214 *
## whiteNot Whit:3 -0.377537 0.156729 -2.409 0.01600 *
## age:1 -0.016349 0.004013 -4.074 4.62e-05 ***
## age:2 -0.024976 0.002832 -8.820 < 2e-16 ***
## age:3 -0.018690 0.003734 -5.005 5.59e-07 ***
## ed:1 0.103247 0.024987 4.132 3.59e-05 ***
## ed:2 0.055869 0.018252 3.061 0.00221 **
## ed:3 0.056685 0.025138 2.255 0.02414 *
## prst:1 -0.001691 0.005594 -0.302 0.76243
## prst:2 0.009848 0.003778 2.606 0.00915 **
## prst:3 0.004922 0.004799 1.026 0.30506
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Number of linear predictors: 3
##
## Names of linear predictors:
## logit(P[Y>=2]), logit(P[Y>=3]), logit(P[Y>=4])
##
## Dispersion Parameter for cumulative family: 1
##
## Residual deviance: 5640.622 on 6858 degrees of freedom
##
## Log-likelihood: -2820.311 on 6858 degrees of freedom
##
## Number of iterations: 6
##
## Exponentiated coefficients:
## yr891989:1 yr891989:2 yr891989:3 maleMen:1
## 2.6006059 1.7097922 1.3926643 0.7400903
## maleMen:2 maleMen:3 whiteNot Whit:1 whiteNot Whit:2
## 0.4877299 0.3376933 0.5893530 0.7052281
## whiteNot Whit:3 age:1 age:2 age:3
## 0.6855475 0.9837842 0.9753329 0.9814834
## ed:1 ed:2 ed:3 prst:1
## 1.1087656 1.0574594 1.0583225 0.9983103
## prst:2 prst:3
## 1.0098962 1.0049346
Note that the above estimates need to be exponentiated to get the estimates as odds-ratios.
You can also do this (with the resuts being shown in terms of odds-ratios of the estimates):
sf = function(y)
c('Y>=1'=qlogis(mean(y >= 1)),'Y>=2'=qlogis(mean(y >= 2)),'Y>=3'=qlogis(mean(y >= 3)), 'Y>=4'=qlogis(mean(y >= 4)))
s = summary(as.numeric(warm) ~ yr89 + male + white + age + ed + prst, data = ordwarm2a, fun=sf)
s
## as.numeric(warm) N=2293
##
## +-------+--------+----+----+--------+-----------+---------+
## | | |N |Y>=1|Y>=2 |Y>=3 |Y>=4 |
## +-------+--------+----+----+--------+-----------+---------+
## |yr89 |1977 |1379|Inf |1.577580|-0.01885480|-1.678001|
## | |1989 | 914|Inf |2.637886| 0.59937902|-1.272566|
## +-------+--------+----+----+--------+-----------+---------+
## |male |Women |1227|Inf |2.057622| 0.50431094|-1.110602|
## | |Men |1066|Inf |1.748649|-0.09387751|-2.132227|
## +-------+--------+----+----+--------+-----------+---------+
## |white |White | 283|Inf |2.334084| 0.49765516|-1.131870|
## | |Not Whit|2010|Inf |1.854688| 0.18359858|-1.563574|
## +-------+--------+----+----+--------+-----------+---------+
## |age |[18,32) | 614|Inf |2.537218| 0.74241823|-1.344077|
## | |[32,43) | 542|Inf |2.141098| 0.52857757|-1.133355|
## | |[43,59) | 598|Inf |1.679281| 0.02675745|-1.523615|
## | |[59,89] | 539|Inf |1.467098|-0.42560522|-2.258490|
## +-------+--------+----+----+--------+-----------+---------+
## |ed |[ 0,12) | 670|Inf |1.452922|-0.27029033|-1.863218|
## | |12 | 782|Inf |1.831099| 0.18982628|-1.612510|
## | |[13,15) | 362|Inf |2.518294| 0.66427920|-1.212371|
## | |[15,20] | 479|Inf |2.540477| 0.66199201|-1.163699|
## +-------+--------+----+----+--------+-----------+---------+
## |prst |[12,31) | 585|Inf |1.717940|-0.03077166|-1.665879|
## | |[31,38) | 568|Inf |1.852639| 0.12693071|-1.683064|
## | |[38,51) | 731|Inf |1.913475| 0.28369324|-1.440174|
## | |[51,82] | 409|Inf |2.307976| 0.62065168|-1.195516|
## +-------+--------+----+----+--------+-----------+---------+
## |Overall| |2293|Inf |1.905168| 0.22157369|-1.503811|
## +-------+--------+----+----+--------+-----------+---------+
These models can also be fit via a variety of other packages, and polr in the MASS
package is useful at times. For example, if I wanted to show the testing of the proportional odds assumption and to put my overall results in stargazer the rms
package won’t work with stargazer. So I show you a quick example below:
library(MASS)
modL = polr(warm ~ yr89 + male + white + age + ed + prst, data = ordwarm2a, method="logistic", Hess=TRUE)
summary(modL)
## Call:
## polr(formula = warm ~ yr89 + male + white + age + ed + prst,
## data = ordwarm2a, Hess = TRUE, method = "logistic")
##
## Coefficients:
## Value Std. Error t value
## yr891989 0.523912 0.079899 6.557
## maleMen -0.733309 0.078483 -9.344
## whiteNot Whit -0.391140 0.118381 -3.304
## age -0.021666 0.002469 -8.777
## ed 0.067176 0.015975 4.205
## prst 0.006072 0.003293 1.844
##
## Intercepts:
## Value Std. Error t value
## SD|D -2.4654 0.2389 -10.3188
## D|A -0.6309 0.2333 -2.7042
## A|SA 1.2618 0.2340 5.3919
##
## Residual Deviance: 5689.825
## AIC: 5707.825
modP = polr(warm ~ yr89 + male + white + age + ed + prst, data = ordwarm2a, method="probit", Hess=TRUE)
summary(modP)
## Call:
## polr(formula = warm ~ yr89 + male + white + age + ed + prst,
## data = ordwarm2a, Hess = TRUE, method = "probit")
##
## Coefficients:
## Value Std. Error t value
## yr891989 0.318813 0.046852 6.805
## maleMen -0.417028 0.045546 -9.156
## whiteNot Whit -0.226500 0.069478 -3.260
## age -0.012221 0.001443 -8.471
## ed 0.038724 0.009324 4.153
## prst 0.003283 0.001925 1.705
##
## Intercepts:
## Value Std. Error t value
## SD|D -1.4286 0.1388 -10.2942
## D|A -0.3606 0.1369 -2.6333
## A|SA 0.7682 0.1371 5.6047
##
## Residual Deviance: 5697.222
## AIC: 5715.222
Predictions from polr() are straightforward and predicted prbabilities can then be plotted (as usual).
newdata.e = data.frame(yr89="1977", male="Women", white="Not Whit", age=seq(18, 89, by=1), ed=12.22, prst=39.59)
yhat.modL = predict(modL, newdata=newdata.e, type="probs")
head(yhat.modL)
## SD D A SA
## 1 0.06034093 0.2264391 0.4406661 0.2725539
## 2 0.06158115 0.2296507 0.4404886 0.2682795
## 3 0.06284515 0.2328791 0.4402280 0.2640478
## 4 0.06413332 0.2361231 0.4398845 0.2598591
## 5 0.06544605 0.2393821 0.4394581 0.2557138
## 6 0.06678374 0.2426548 0.4389493 0.2516121
yhat.modP = predict(modP, newdata=newdata.e, type="probs")
head(yhat.modP)
## SD D A SA
## 1 0.05645347 0.2460382 0.4270659 0.2704424
## 2 0.05785475 0.2489154 0.4268165 0.2664134
## 3 0.05928323 0.2517919 0.4265099 0.2624149
## 4 0.06073922 0.2546669 0.4261464 0.2584474
## 5 0.06222303 0.2575396 0.4257261 0.2545113
## 6 0.06373496 0.2604092 0.4252491 0.2506067
library(stargazer)
stargazer(modL, modP, type="html")
Dependent variable: | ||
warm | ||
ordered | ordered | |
logistic | probit | |
(1) | (2) | |
yr891989 | 0.524*** | 0.319*** |
(0.080) | (0.047) | |
maleMen | -0.733*** | -0.417*** |
(0.078) | (0.046) | |
whiteNot Whit | -0.391*** | -0.226*** |
(0.118) | (0.069) | |
age | -0.022*** | -0.012*** |
(0.002) | (0.001) | |
ed | 0.067*** | 0.039*** |
(0.016) | (0.009) | |
prst | 0.006* | 0.003* |
(0.003) | (0.002) | |
Observations | 2,293 | 2,293 |
Note: | p<0.1; p<0.05; p<0.01 |
load("~/Box Sync/MPA6020/Data/autos.RData")
The autos data-frame has 74 observations on the following variables:
Let us fit a small model with rep78 as the outcome of interest. We’ll use only a couple of independent variables – price, mpg and foreign.
The NHANES – the national health and nutrition examination survey – data have a variable called health that will be used as the ordinal response of interest. Some possible independent variables could be sex, race, age, and region.
load("~/Box Sync/MPA6020/Data/nhanes2f.RData")