Ordinal Logistic Regression Power Analysis (original) (raw)

# adopted from Greg Snow's answer on CV:
#  https://stats.stackexchange.com/questions/22406/power-analysis-for-ordinal-logistic-regression/22410#22410

Step 1: Define design and NA condition to solve

library(SimDesign)

Design <- createDesign(n = NA,
                       beta0 = -1/2, beta1 = 1/4, beta2 = 1/4)
Design
# A tibble: 1 × 4
      n beta0 beta1 beta2
  <dbl> <dbl> <dbl> <dbl>
1    NA  -0.5  0.25  0.25

Step 2 — Define analyse and summarise functions

Analyse <- function(condition, dat, fixed_objects = NULL) {
    Attach(condition)
    x <- runif(n, 0, 10)
    eta1 <- beta0 + beta1*x
    eta2 <- eta1 + beta2
    p1 <- exp(eta1)/(1+exp(eta1))
    p2 <- exp(eta2)/(1+exp(eta2))
    tmp <- runif(n)
    y <- (tmp < p1) + (tmp < p2)
    fit <- rms::lrm(y~x)
    fit$stats[5]
}

Summarise <- function(condition, results, fixed_objects = NULL) {
    ret <- ERR(results, alpha = .05)  ## empirical rejection rate given alpha
    ret
}

Step 3 — Optimize over the rows in design

# find n associated with f(n) = 1 - B = .90 power
# terminate when prediction CI between [.895, .905]
solved <- SimSolve(design=Design, b=.9, interval=c(30,300), parallel=TRUE,
                   analyse=Analyse, summarise=Summarise,
                   predCI.tol=.01, maxiter = 200, verbose=FALSE)
solved
# A tibble: 1 × 4
       n beta0 beta1 beta2
   <dbl> <dbl> <dbl> <dbl>
1 96.631  -0.5  0.25  0.25
summary(solved)  # note that prediction CI is within [.895, .905]
$root
[1] 96.63137

$predCI.root
  CI_2.5  CI_97.5 
95.29939 97.81995 

$b
[1] 0.9

$predCI.b
[1] 0.8951701 0.9046310

$terminated_early
[1] TRUE

$time
[1] 33.62s

$iterations
[1] 80

$total.replications
[1] 22900

$tab
           y   x reps
5  0.8837736  92 2650
6  0.8909910  93 1110
7  0.8993399  94 3030
8  0.8964602  95 2260
9  0.8859873  96 1570
10 0.8960606  97 3300
11 0.9071429  98 2100
12 0.9082667  99 3750
13 0.9186667 100 1500
15 0.9093750 102  320
plot(solved, type = 'history')