Likelihood Ratios
Menu location: Analysis_Clinical Epidemiology_Likelihood Ratios (2 by k).
This function gives likelihood ratios and their confidence intervals for each of two or more levels of results from a test (Interpretation of diagnostic data, 1983; Sackett et al., 1991).
The quality of a diagnostic test can be expressed in terms of sensitivity and specificity. Sensitivity is the ability of the test to pick up what it is testing for and specificity is the ability of the test to reject what it is not testing for.
| DISEASE | |||
| Present | Absent | ||
| TEST: | +: | a (true +ve) | b (false +ve) |
| -: | c (false -ve) | d (true -ve) | |
Sensitivity = a/(a+c)
Specificity = d/(b+d)
Likelihood ratio of a positive test = [a/(a+c)]/[b/(b+d)]
Likelihood ratio of a negative test = [c/(a+c)]/[d/(b+d)]
Likelihood ratios enable you to quantify the effect that a particular test result has on the probability of an outcome (e.g. diagnosis of a disease). Using a simplified form of Bayes' theorem:
posterior odds = prior odds * likelihood ratio
where:
odds = probability/(1-probability)
probability = odds/(odds+1)
These methods can be generalised to more than two possible test outcomes, in which case the data can be arranged into a two by k table (k is the number of test outcomes studied). If one test outcome is called test level j then the likelihood ratio at level j is given by:
likelihood ratio j = p(tj_disease)/p(tj_no disease)
where p(tj_) is the proportion displaying the relevant test result at level j
Technical validation
The confidence intervals for the likelihood ratios are constructed using the iterative method suggested by Gart and Nam (1988).
Example
From Sackett et al. (1991, p. 111).
Initial creatine phosphokinase (CK) levels were related to the subsequent diagnosis of acute myocardial infarction (MI) in a group of patients with suspected MI. Four ranges of CK result were chosen for the study:
| MI | No MI | |
| CK ≥ 280: | 97 | 1 |
| CK = 80-279: | 118 | 15 |
| CK = 40-79: | 13 | 26 |
| CK = 1-39: | 2 | 88 |
To analyse these data in StatsDirect select Likelihood Ratios (2 by K) from the Clinical Epidemiology section of the Analysis menu. Choose the default 95% confidence interval.
For this example:
| Result | + Feature | - Feature | Likelihood Ratio | 95% CI (Koopman) |
| 1 | 97 | 1 | 54.826087 | 9.923105 to 311.581703 |
| 2 | 118 | 15 | 4.446377 | 2.772565 to 7.31597 |
| 3 | 13 | 26 | 0.282609 | 0.151799 to 0.524821 |
| 4 | 2 | 88 | 0.012846 | 0.003513 to 0.046227 |
Here we can say with 95% confidence that CK results of ≥ 280 are at least ten (9.9) times more likely to come from patients who have had an MI than they are to come from those who have not had an MI.
R code
This R code reproduces the example above. It needs no packages and was checked with R 4.6.1. Paste it into R, or save it as a script and run it.
# Likelihood ratios for the levels of a test: the StatsDirect help example (Sackett et
# al. 1991, p. 111, initial creatine kinase levels of 230 patients who had an acute
# myocardial infarction and 130 who had not, in four ranges of CK) in R
ck <- c("280 or more", "80 to 279", "40 to 79", "1 to 39")
mi <- c(97, 118, 13, 2) # + feature: patients with an MI at each CK level
no_mi <- c(1, 15, 26, 88) # - feature: patients without an MI at each CK level
counts <- cbind(MI = mi, "No MI" = no_mi)
rownames(counts) <- ck
print(addmargins(counts))
# The likelihood ratio of a level is the proportion of the MI patients at that level
# over the proportion of the non-MI patients there; the proportions come from
# prop.table applied down the columns
p <- prop.table(counts, margin = 2)
print(p, digits = 4)
lr <- p[, "MI"] / p[, "No MI"]
print(lr, digits = 7)
# Base R has no function for the confidence interval of a ratio of two binomial
# proportions, so the limits are found as Koopman (1984) defines them: the ratios at
# which the score chi-square, with the two proportions estimated under the constraint
# that they have that ratio, reaches the chi-square critical value for the chosen level
# (95% here). Every count in the example is greater than zero, which this function
# assumes.
koopman <- function(x1, n1, x0, n0, level = 0.95) {
chi2 <- function(theta) {
A <- (n0 + n1) * theta
B <- -((x0 + n1) * theta + x1 + n0)
p0 <- (-B - sqrt(B^2 - 4 * A * (x0 + x1))) / (2 * A) # constrained estimate
p1 <- theta * p0
(x1 - n1 * p1)^2 / (n1 * p1 * (1 - p1)) *
(1 + n1 * (theta - p1) / (n0 * (1 - p1)))
}
est <- (x1 / n1) / (x0 / n0)
f <- function(lt) chi2(exp(lt)) - qchisq(level, 1)
lower <- exp(uniroot(f, c(log(est) - 20, log(est)), tol = 1e-12)$root)
upper <- exp(uniroot(f, c(log(est), log(est) + 20), tol = 1e-12)$root)
c(est, lower, upper)
}
# The report's table: one row per level, numbered in the order given
six <- function(x) formatC(x, digits = 6, format = "f", drop0trailing = TRUE)
cat("Result + Feature - Feature Likelihood Ratio 95% CI (Koopman)\n")
for (i in seq_along(mi)) {
k <- koopman(mi[i], sum(mi), no_mi[i], sum(no_mi))
cat(i, " ", mi[i], " ", no_mi[i], " ", six(k[1]), " ", six(k[2]), " to ", six(k[3]),
"\n", sep = "")
}
# Bayes' theorem in odds form: with a prior probability of MI of 0.5, say, the prior
# odds are 1, and a CK of 280 or more multiplies them by that level's likelihood ratio
prior <- 0.5
posterior_odds <- prior / (1 - prior) * lr[1]
cat("Posterior probability of MI given CK of 280 or more =",
six(posterior_odds / (posterior_odds + 1)), "\n")