Plot Positive and Negative Predictive Values for Medical Tests
Functions to plot and help understand positive and negative predictive values (PPV and NPV), and their relationship with sensitivity, specificity, and prevalence. See Akobeng, A.K. (2007) <doi:10.1111/j.1651-2227.2006.00180.x> for a theoretical overview of the technical concepts and Navarrete et al. (2015) for a practical explanation about the importance of their understanding <doi:10.3389/fpsyg.2015.01327>.
Bayesian reasoning in medical contexts
This package includes a few functions to plot and help understand Positive and Negative Predictive Values, and their relationship with Sensitivity, Specificity and Prevalence.
- The Positive Predictive Value of a medical test is the probability that a positive result will mean having the disease. Formally p(Disease|+)
- The Negative Predictive Value of a medical test is the probability that a negative result will mean not having the disease. Formally p(Healthy|-)
The BayesianReasoning package has three main functions:
- PPV_heatmap(): Plot heatmaps with PPV or NPV values for the given test and disease parameters.
- PPV_diagnostic_vs_screening(): Plots the difference between the PPV of a test in a diagnostic context (very high prevalence; or a common study sample, e.g. ~50% prevalence) versus a screening context (lower prevalence).
- min_possible_prevalence(): Calculates how high should the prevalence of a disease be to reach a desired PPV given certain test parameters.
You can install the stable (CRAN) version of the package with
install.packages("BayesianReasoning") or development version with
remotes::install_github("gorkang/BayesianReasoning@dev"). Please report any problems you find in the Issues Github page.
There is a shiny app implementation with most of the main features of the PPV_heatmap() function available.
Plot heatmaps with PPV or NPV values for a given specificity and a range of Prevalences and FP or FN (1 - Sensitivity). The basic parameters are:
- Min_Prevalence: Min prevalence in y axis. "Min_Prevalence out of y"
- Max_Prevalence: Max prevalence in y axis. "1 out of Max_Prevalence"
- Sensitivity: Sensitivity of the test
- Max_FP: FP is 1 - specificity. The x axis will go from FP = 0% to Max_FP
- Language: "es" for Spanish or "en" for English
PPV_heatmap(Min_Prevalence = 1, Max_Prevalence = 1000, Sensitivity = 100, Max_FP = 2, Language = "en")
You can also plot an NPV heatmap with PPV_NPV = "NPV".
PPV_heatmap(PPV_NPV = "NPV", Min_Prevalence = 800, Max_Prevalence = 1000, Sensitivity = 80, Max_FP = 5, Language = "en")
You can add different types of overlay to the plots.
For example, an area overlay showing the point PPV for a given prevalence and FP or FN:
PPV_heatmap(Min_Prevalence = 1, Max_Prevalence = 1200, Sensitivity = 81, Max_FP = 5, label_subtitle = "Prenatal screening for Down Syndrome by Age", folder = "", overlay = "area", overlay_labels = "40 y.o.", overlay_position_FP = 4.8, overlay_prevalence_1 = 1, overlay_prevalence_2 = 68)
Also, you can add a line overlay highlighting a range of prevalences and FP. This is useful, for example, to show how the PPV of a test changes with age:
PPV_heatmap(Min_Prevalence = 1, Max_Prevalence = 1800, Sensitivity = 90, Max_FP = 15, label_subtitle = "PPV of Mammogram for Breast Cancer by Age", overlay = "line", overlay_labels = c("80 y.o.", "70 y.o.", "60 y.o.", "50 y.o.", "40 y.o.", "30 y.o.", "20 y.o."), overlay_position_FP = c(6.5, 7, 8, 9, 12, 14, 14), overlay_prevalence_1 = c(1, 1, 1, 1, 1, 1, 1), overlay_prevalence_2 = c(22, 26, 29, 44, 69, 227, 1667))
Another example. In this case, the FP is constant across age:
PPV_heatmap(Min_Prevalence = 1, Max_Prevalence = 1200, Sensitivity = 81, Max_FP = 5, label_subtitle = "Prenatal screening for Down Syndrome by Age", overlay = "line", overlay_labels = c("40 y.o.", "35 y.o.", "30 y.o.", "25 y.o.", "20 y.o."), overlay_position_FP = c(4.8, 4.8, 4.8, 4.8, 4.8), overlay_prevalence_1 = c(1, 1, 1, 1, 1), overlay_prevalence_2 = c(68, 249, 626, 946, 1068))
In scientific studies developing a new test for the early detection of a medical condition, it is quite common to use a sample where 50% of participants has a medical condition and the other 50% are normal controls. This has the unintended effect of maximizing the PPV of the test.
This function shows a plot with the difference between the PPV of a diagnostic context (very high prevalence; or a common study sample, e.g. ~50% prevalence) versus that of a screening context (lower prevalence).
PPV_diagnostic_vs_screening(Max_FP = 10, Sensitivity = 100, prevalence_screening_group = 1000, prevalence_diagnostic_group = 2)
Imagine you would like to use a test in a population and want to have a 98% PPV. That is, IF a positive result comes out in the test, you would like a 98% certainty that it is a true positive.
How high should the prevalence of the disease be in that group?
min_possible_prevalence(Sensitivity = 100, FP_test = 0.1, min_PPV_desired = 98)
To reach a PPV of 98 when using a test with 100 % Sensitivity and 0.1 % False Positive Rate, you need a prevalence of at least 1 out of 21
Another example, with a very good test, and lower expectations:
min_possible_prevalence(Sensitivity = 99.9, FP_test = .1, min_PPV_desired = 70)
To reach a PPV of 70 when using a test with 99.9 % Sensitivity and 0.1 % False Positive Rate, you need a prevalence of at least 1 out of 429
Functions in BayesianReasoning
|PPV_heatmap||Plot PPV and NPV heatmaps|
|min_possible_prevalence||Show minimum possible prevalence given the test characteristics|
|PPV_diagnostic_vs_screening||Plot PPV values for a diagnostic and a screening group|
Vignettes of BayesianReasoning
Last month downloads
|Packaged||2020-07-03 13:19:34 UTC; emrys|
|Date/Publication||2020-07-03 16:40:16 UTC|
Include our badge in your README