Last updated: 2026-01-06
Checks: 7 0
Knit directory: fiveMinuteStats/analysis/
This reproducible R Markdown analysis was created with workflowr (version 1.7.1). The Checks tab describes the reproducibility checks that were applied when the results were created. The Past versions tab lists the development history.
Great! Since the R Markdown file has been committed to the Git repository, you know the exact version of the code that produced these results.
Great job! The global environment was empty. Objects defined in the global environment can affect the analysis in your R Markdown file in unknown ways. For reproduciblity it’s best to always run the code in an empty environment.
The command set.seed(12345) was run prior to running the
code in the R Markdown file. Setting a seed ensures that any results
that rely on randomness, e.g. subsampling or permutations, are
reproducible.
Great job! Recording the operating system, R version, and package versions is critical for reproducibility.
Nice! There were no cached chunks for this analysis, so you can be confident that you successfully produced the results during this run.
Great job! Using relative paths to the files within your workflowr project makes it easier to run your code on other machines.
Great! You are using Git for version control. Tracking code development and connecting the code version to the results is critical for reproducibility.
The results in this page were generated with repository version 551db67. See the Past versions tab to see a history of the changes made to the R Markdown and HTML files.
Note that you need to be careful to ensure that all relevant files for
the analysis have been committed to Git prior to generating the results
(you can use wflow_publish or
wflow_git_commit). workflowr only checks the R Markdown
file, but you know if there are other scripts or data files that it
depends on. Below is the status of the Git repository when the results
were generated:
working directory clean
Note that any generated files, e.g. HTML, png, CSS, etc., are not included in this status report because it is ok for generated content to have uncommitted changes.
These are the previous versions of the repository in which changes were
made to the R Markdown
(analysis/likelihood_ratio_simple_continuous_data.Rmd) and
HTML (docs/likelihood_ratio_simple_continuous_data.html)
files. If you’ve configured a remote Git repository (see
?wflow_git_remote), click on the hyperlinks in the table
below to view the files as they were in that past version.
| File | Version | Author | Date | Message |
|---|---|---|---|---|
| Rmd | 551db67 | Peter Carbonetto | 2026-01-06 | A few small updates to the likelihood_ratio_simple_continuous_data vignette. |
| html | 551db67 | Peter Carbonetto | 2026-01-06 | A few small updates to the likelihood_ratio_simple_continuous_data vignette. |
| Rmd | cb29296 | Peter Carbonetto | 2025-12-29 | Added pdf version of likelihood_ratio_simple_continuous_data vignette. |
| html | 56054d9 | Matthew Stephens | 2022-04-26 | Build site. |
| Rmd | 4a62d37 | GitHub | 2022-04-26 | Fix typo in likelihood_ratio_simple_continuous_data.Rmd |
| html | 5f62ee6 | Matthew Stephens | 2019-03-31 | Build site. |
| Rmd | 0cd28bd | Matthew Stephens | 2019-03-31 | workflowr::wflow_publish(all = TRUE) |
| html | 34bcc51 | John Blischak | 2017-03-06 | Build site. |
| Rmd | 5fbc8b5 | John Blischak | 2017-03-06 | Update workflowr project with wflow_update (version 0.4.0). |
| Rmd | 391ba3c | John Blischak | 2017-03-06 | Remove front and end matter of non-standard templates. |
| html | 8e61683 | Marcus Davy | 2017-03-03 | rendered html using wflow_build(all=TRUE) |
| html | 5d0fa13 | Marcus Davy | 2017-03-02 | wflow_build() rendered html files |
| Rmd | d674141 | Marcus Davy | 2017-02-26 | typos, refs |
| html | c3b365a | John Blischak | 2017-01-02 | Build site. |
| Rmd | 67a8575 | John Blischak | 2017-01-02 | Use external chunk to set knitr chunk options. |
| Rmd | 5ec12c7 | John Blischak | 2017-01-02 | Use session-info chunk. |
| Rmd | 9714939 | stephens999 | 2016-03-28 | add example to show how approximation can break down |
| Rmd | a424331 | stephens999 | 2016-01-19 | minor update |
| Rmd | 8b7278d | stephens999 | 2016-01-11 | add LR for continuous data |
See here for a PDF version of this vignette.
This document introduces the likelihood ratio for continuous data and models, and explains its connection with discrete models.
Be familiar with the likelihood ratio for discrete data.
Recall that if \(M_0\) and \(M_1\) are fully-specified models for discrete data \(X = x\), with probability mass functions \(p(x \mid M_0)\) and \(p(x \mid M_1)\), then the likelihood ratio for \(M_1\) vs. \(M_0\) is \[ \mathrm{LR}(M_1,M_0) := \frac{p(x \mid M_1)}{p(x \mid M_0)}. \] Now suppose that the data and models are continuous. So instead of a probability mass function, each model has a probability density function. Then the likelihood ratio for \(M_1\) vs. \(M_0\) is usually defined as the ratio of the probability density functions. That is, we have exactly the same expression for the LR, \[ \mathrm{LR}(M_1,M_0) := \frac{p(x \mid M_1)}{p(x \mid M_0)}, \] but now \(p(\cdot | M_1)\) and \(p(\cdot | M_0)\) are probability density functions instead of probability mass functions.
A medical screening test for a disease involves measuring the concentration (\(X\)) of a protein in the blood. In normal individuals, \(X\) has a Gamma distribution with mean 1 and shape 2. In diseased individuals, the protein becomes elevated, and \(X\) has a Gamma distribution with mean 2 and shape 2. Plotting the probability density functions of these distributions yields:
x <- seq(0,10,length.out = 100)
plot(x,dgamma(x,scale = 0.5,shape = 2),type = "l",col = "blue",lwd = 2,
xlab = "protein concentration",ylab = "probability density")
lines(x,dgamma(x,scale = 1,shape = 2),type = "l",col = "red",lwd = 2)

Suppose that for a particular patient we observe \(X=4.02\). Then the likelihood ratio for the
model that this patient is from the normal group (\(M_n\)) vs. the model that the patient is
from the diseased group (\(M_d\)) is
dgamma(4.02,scale = 0.5,shape = 2)/dgamma(4.02,scale = 1,shape = 2)
which is 0.0718. That is, the data favour this individual being diseased
by a factor of approximately 14.
Often the likelihood ratio for continuous models is simply defined as the ratio of the densities, as above. However, an alternative approach, which can yield greater insight, is instead to derive this result as an approximation, from the definition of likelihood ratio for discrete models, as follows.
The first step is to recognize that in practice all observations are actually discrete, because of finite precision. Sometimes the measurement precision is made explicit, but often it is implicit in the number of decimal places used to report an observation. For example, in the example above, where we were told that we observed a protein concentration of \(X=4.02\), it would be reasonable to think that the measurement precision is 2 decimal places, and that this observation actually corresponds to “\(X\) lies in the interval \([4.015,4.025)\)”. The probability of this observation, under a continuous model for \(X\), is the integral of the probability density function from \(4.015\) to \(4.025\). In other words, it is \(F_X(4.025) - F_X(4.015)\), where \(F_X\) denotes the cumulative distribution function for \(X\).
With this view, the likelihood for the “observation” \(X=4.02\) under \(M_n\) is actually
pgamma(4.025,scale = 0.5,shape = 2) - pgamma(4.015,scale = 0.5,shape = 2),
which is 0.00005183. Similarly, the likelihood under \(M_d\) is 0.0007217, and therefore the
likelihood ratio is 0.0718126.
As you can see, this approach yields a LR that is numerically very close to that obtained using the ratio of the densities, as above. This is not a coincidence! Here is why we should expect this to happen more generally. Suppose we assume that the measurement precision is \(\epsilon\). So the “observation” \(X = x\) really means \(X \in [x-\epsilon, x+\epsilon]\). Then the likelihood for a model \(M\), given this observation, is \(\Pr(X \in [x-\epsilon,x+\epsilon] \mid M)\). Provided that the density \(p(x \mid M)\) is approximately constant in the region within radius \(\epsilon\) around \(x\), then this probability is approximately \(2 \epsilon p(x \mid M)\). Thus, the LR for two models \(M_1\) vs. \(M_0\) is \[ LR = \frac{\Pr(X \in [x-\epsilon,x+\epsilon] \mid M_1)} {\Pr(X \in [x-\epsilon,x+\epsilon] \mid M_0)} \approx \frac{2\epsilon p(x \mid M_1)}{2\epsilon p(x \mid M_0)} = \frac{p(x \mid M_1)}{p(x \mid M_0)}. \]
The approximation usually works well, but here is a simple example to illustrate how the approximation could break down in principle.
Consider observing a single data point \(X\) and we compare the models that \(M_0: X \sim N(0, \sigma_0)\) vs. \(M_1: X \sim N(0, \sigma_1)\). Suppose that we observe \(X = 0.00\), assumed to be correct to the nearest 0.01. So the “true” LR is given by
trueLR <- function (s0, s1) {
L0 <- pnorm(0.005,sd = s0) - pnorm(-0.005,sd = s0)
L1 <- pnorm(0.005,sd = s1) - pnorm(-0.005,sd = s1)
return(L0/L1)
}
and the approximation is
approxLR <- function (s0, s1)
dnorm(0,sd = s0)/dnorm(0,sd = s1)
Now, if \(\sigma_0\) and \(\sigma_1\) are both not too small, the approximation works fine. For example, for \(\sigma_0 = 0.5, \sigma_1 = 1\), the truth and approximation are 1.999975 and 2.
But \(\sigma_0\) or \(\sigma_1\) is small, we have the problem that the density is not approximately constant within the region \([-0.005, 0.005]\). For example, at \(\sigma_0 = 0.001, \sigma_1 = 1\) we have the truth and approximation as 250.6637282 and 1000.
In most cases, the likelihood ratio for model \(M_1\) vs. model \(M_0\) for a continuous random variable \(X\), given an observation \(X = x\), can be well approximated by the ratio of the model densities of \(X\), evaluated at \(x\). This approximation comes from assuming that the model density functions are approximately constant within the neighborhood of \(x\) that has radius equal to the measurement precision.
sessionInfo()
# R version 4.3.3 (2024-02-29)
# Platform: aarch64-apple-darwin20 (64-bit)
# Running under: macOS 15.7.1
#
# Matrix products: default
# BLAS: /Library/Frameworks/R.framework/Versions/4.3-arm64/Resources/lib/libRblas.0.dylib
# LAPACK: /Library/Frameworks/R.framework/Versions/4.3-arm64/Resources/lib/libRlapack.dylib; LAPACK version 3.11.0
#
# locale:
# [1] en_US.UTF-8/en_US.UTF-8/en_US.UTF-8/C/en_US.UTF-8/en_US.UTF-8
#
# time zone: America/Chicago
# tzcode source: internal
#
# attached base packages:
# [1] stats graphics grDevices utils datasets methods base
#
# loaded via a namespace (and not attached):
# [1] vctrs_0.6.5 cli_3.6.5 knitr_1.50 rlang_1.1.6
# [5] xfun_0.52 stringi_1.8.7 promises_1.3.3 jsonlite_2.0.0
# [9] workflowr_1.7.1 glue_1.8.0 rprojroot_2.0.4 git2r_0.33.0
# [13] htmltools_0.5.8.1 httpuv_1.6.14 sass_0.4.10 rmarkdown_2.29
# [17] evaluate_1.0.4 jquerylib_0.1.4 tibble_3.3.0 fastmap_1.2.0
# [21] yaml_2.3.10 lifecycle_1.0.4 whisker_0.4.1 stringr_1.5.1
# [25] compiler_4.3.3 fs_1.6.6 Rcpp_1.1.0 pkgconfig_2.0.3
# [29] later_1.4.2 digest_0.6.37 R6_2.6.1 pillar_1.11.0
# [33] magrittr_2.0.3 bslib_0.9.0 tools_4.3.3 cachem_1.1.0