Ordered Logit
inv_logit <- function(x) {
p <- 1 / (1 + exp(-x))
return(p)
}
ologit <- function(data, formula, na.action=na.exclude) {
mf <- model.frame(formula, data, na.action=na.exclude)
Y <- model.response(mf)
X <- model.matrix(formula, mf)[,-1]
N <- nrow(X)
levels <- unique(Y) |> sort()
M <- length(levels)
ncut <- M-1
c <- 1:ncut/M
b <- numeric(ncol(X))
par <- c(c,b)
ologitLL <- function(param) {
c <- param[1:ncut]
b <- param[(ncut+1):length(param)]
Xb <- X %*% b
lli <- numeric(N)
for (m in 1:M) {
if (m == 1) {
lli[Y==levels[m]] <- log(inv_logit(c[m]-Xb[Y==levels[m]]))
} else if (m < M) {
lli[Y==levels[m]] <- log(inv_logit(c[m]-Xb[Y==levels[m]]) - inv_logit(c[m-1]-Xb[Y==levels[m]]))
} else {
lli[Y==levels[m]] <- log(1 - inv_logit(c[m-1]-Xb[Y==levels[m]]))
}
}
return(-sum(lli))
}
out <- optim(par, ologitLL, method="BFGS")
est <- out$par
names(est)[1:ncut] <- paste0("t", 1:ncut)
names(est)[(ncut+1):length(est)] <- colnames(X)
return(est)
}Testing the function:
# Example from https://towardsdatascience.com/implementing-and-interpreting-ordinal-logistic-regression-1ee699274cf5
library(carData)
library(MASS)
data(WVS)
f <- poverty~religion+degree+country+age+gender
summary(polr(f, WVS))##
## Re-fitting to get Hessian
## Call:
## polr(formula = f, data = WVS)
##
## Coefficients:
## Value Std. Error t value
## religionyes 0.17973 0.077346 2.324
## degreeyes 0.14092 0.066193 2.129
## countryNorway -0.32235 0.073766 -4.370
## countrySweden -0.60330 0.079494 -7.589
## countryUSA 0.61777 0.070665 8.742
## age 0.01114 0.001561 7.139
## gendermale 0.17637 0.052972 3.329
##
## Intercepts:
## Value Std. Error t value
## Too Little|About Right 0.7298 0.1041 7.0128
## About Right|Too Much 2.5325 0.1103 22.9496
##
## Residual Deviance: 10402.59
## AIC: 10420.59
ologit(WVS, f)## Warning in log(inv_logit(c[m] - Xb[Y == levels[m]]) - inv_logit(c[m - 1] - :
## NaNs produced
## Warning in log(inv_logit(c[m] - Xb[Y == levels[m]]) - inv_logit(c[m - 1] - :
## NaNs produced
## Warning in log(inv_logit(c[m] - Xb[Y == levels[m]]) - inv_logit(c[m - 1] - :
## NaNs produced
## t1 t2 religionyes degreeyes countryNorway
## 0.72937251 2.53210358 0.17978268 0.14087551 -0.32235825
## countrySweden countryUSA age gendermale
## -0.60330084 0.61782030 0.01113128 0.17637937