Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

probit ordinal logistic regression with `MASS::polr`: How to make prediction on new data

I want to do ordinal regression in R, so I want to use the polr function from the MASS package. First I create a model like this:

model <- polr(labels ~ var1 + var2, Hess = TRUE)  

Now I want to use the model to predict new cases. I thought that would simply be:

pred <- predict(model, data = c(newVar1, newVar2))  

However it seems that predict is somehow predicting on the training set, not the new data. When my training set is 2000 examples, and my new data is 700 examples. I still get 2000 predicted labels.

So my question is: how do I use polr to make predictions on new data?

like image 228
dimpol Avatar asked Sep 01 '25 22:09

dimpol


1 Answers

Sadly there is no documentation entry for predict.polr, otherwise you can simply read that for how to use predict correctly.

In R, only for few primitive model fitting functions like smooth.spline, predict expect a vector for newdata (this is reasonable as smooth.spline handles univariate regression). Generally, predict expects a data frame or list, whose names match variables specified in model formula or as shown in model frame (the "terms" attributes). If you fit a model:

labels ~ var1 + var2

then you should construct newdata:

predict(model, newdata = data.frame(var1 = newVar1, var2 = newVar2))

or

predict(model, newdata = list(var1 = newVar1, var2 = newVar2))

Note, it is newdata, not data for predict.


Since there is no documentation, it may be good if we look at:

args(MASS:::predict.polr)
#function (object, newdata, type = c("class", "probs"), ...) 

and you can even check source code (not long):

MASS:::predict.polr

You will see in source code:

newdata <- as.data.frame(newdata)
m <- model.frame(Terms, newdata, na.action = function(x) x, 
       xlev = object$xlevels)

This explains why newdata should be passed as a data frame, and why variable names must match what is in Terms.


Here is a reproducible example:

library(MASS)
house.plr <- polr(Sat ~ Infl + Type + Cont, weights = Freq, data = housing)

## check model terms inside model frame
attr(terms(house.plr$model), "term.labels")
# [1] "Infl" "Type" "Cont"

When making prediction, these will not work:

## `data` ignored as no such argument
predict(house.plr, data = data.frame("Low", "Tower", "Low"))
## no_match in names 
predict(house.plr, newdata = data.frame("Low", "Tower", "Low"))

This works:

predict(house.plr, newdata = data.frame(Infl = "Low", Type = "Tower", Cont = "Low"))

#[1] Low
#Levels: Low Medium High
like image 146
Zheyuan Li Avatar answered Sep 03 '25 15:09

Zheyuan Li