In Chapter 9 we saw that for a linear model, the Cox-Snell formula gives exactly the same answer as ordinary \(R^2\), but the naive proportional reduction in deviance doesn’t. In this appendix we’ll look at what happens to these measures when the outcome isn’t continuous, and why the different versions don’t agree.
C.1 Two formulas
For models fit by maximum likelihood, there’s no SSE, so we have to build something like \(R^2\) out of the deviance instead. Different people have done this in different ways.
Proportional reduction in deviance (McFadden’s) works just like PRE:
\[\text{PRD} = \frac{D_0 - D_1}{D_0}\]
Cox and Snell’s is based on the likelihood ratio and adjusts for the sample size:
Cox-Snell is exactly the same as \(R^2\), but PRD isn’t even close.
So Cox-Snell is a real generalization of \(R^2\). When the model is linear, it gives you \(R^2\). PRD just looks like PRE, and for a linear model it’s wrong. As we saw in Chapter 9, the problem is the \(\sigma\) estimate: as RSS goes to zero, \(\sigma\) goes to zero and the likelihood goes to infinity, so the ratio of deviances doesn’t work.
But neither one can tell you what the \(R^2\) would have been if a binary outcome hadn’t been dichotomized in the first place. That’s what the rest of this appendix shows.
C.3 A controlled comparison
We can make up data where we know the truth. We’ll generate two variables with an exact correlation, so we know the “latent” \(R^2\). Then we’ll dichotomize the outcome and see what the two measures say.
# create dataset with exact known correlation# convert outcome to binary and see if PRD = Cox-Snellget_stats <-function(n, r) { Sigma <-matrix(c(1, r, r, 1), 2, 2) mat <- MASS::mvrnorm(n, mu =c(0, 0), Sigma = Sigma, empirical =TRUE) x = mat[,1] ystar = mat[,2] y =if_else(ystar >0, 1, 0) # binom transform m0 <-glm(y ~1, family =binomial()) m1 <-glm(y ~ x, family =binomial()) d0 <-as.numeric(-2*logLik(m0)) d1 <-as.numeric(-2*logLik(m1)) delta <- d0 - d1 prd <- (d0 - d1) / d0 cs <-1-exp(-delta /length(x)) tmp <- tibble::tibble(cs = cs,prd = prd )return(tmp)}set.seed(522)# for a given PRE (r2), get the data and compare stats for increasing Nmytests <-expand_grid(n =seq(50, 1000, 50),r =c(sqrt(.1), sqrt(.5), sqrt(.8))) |>rowwise() |>mutate(stats =list(get_stats(n, r))) |>unnest_wider(stats) |>ungroup() |>mutate(latent =factor(round(r^2, 1)))mytests |>select(n, latent, prd, cs) |>head(4) |>mutate(across(c(prd, cs), \(z) round(z, 4)))
The two measures don’t agree. When the latent \(R^2\) is .1, Cox-Snell is about a third bigger than PRD. At .8, PRD is usually the bigger one. So you can’t convert one into the other, and one isn’t even consistently bigger than the other.
Neither one recovers the latent \(R^2\). When the truth is .8, both give values between about .5 and .7. When you dichotomize an outcome, you throw information away, and no summary statistic can get it back. (This is a different problem from the linear model above, where Cox-Snell was exactly right and PRD was wrong. Here, Cox-Snell is doing what it’s supposed to do. It’s the dichotomization that lost the information.)
Cox-Snell can’t reach 1. For a binary outcome, its maximum is less than 1. That’s why there’s yet another version (Nagelkerke’s), which rescales Cox-Snell by its maximum. But that has its own problems.
ImportantThe practical rule
If your readers expect a pseudo-\(R^2\), go ahead and report one, but say which one it is. Don’t compare a pseudo-\(R^2\) to an ordinary \(R^2\) from a different model, and don’t compare pseudo-\(R^2\) values from different formulas.
To compare models fit to the same data, I’d use the information criteria from Chapter 10 instead. And to describe how much a predictor matters, the average marginal effects from Chapter 16 tell you a lot more than any single measure of fit.