Analysis of Diagnostic Accuracy Measures for Two Combined Diagnostic Tests

Theodora Chatzimichail, MD  
tc@hcsl.com
Aristides T. Hatjimihail, MD, PhD
 ath@hcsl.com

Hellenic Complex Systems Laboratory, Kostis Palamas 21, 66131 Drama, Greece.

Initialization Code

senss[{x1_,x2_},{{μ1H_,μ2H_},{σ1H_,σ2H_}, ρH_},{{μ1D_,μ2D_},{σ1D_,σ2D_}, ρD_}]:=
1-CDF[BinormalDistribution[{μ1D,μ2D},{σ1D,σ2D}, ρD],{InverseCDF[NormalDistribution[μ1H,σ1H],x1],InverseCDF[NormalDistribution[μ2H,σ2H],x2]}]

specs[{x1_,x2_},{{μ1H_,μ2H_},{σ1H_,σ2H_}, ρH_},{{μ1D_,μ2D_},{σ1D_,σ2D_}, ρD_}]:=
CDF[BinormalDistribution[{μ1H, μ2H},{σ1H,σ2H}, ρH],{InverseCDF[NormalDistribution[μ1D,σ1D],1-x1],InverseCDF[NormalDistribution[μ2D,σ2D],1-x2]}]

sens[{x1_,x2_},{{μ1H_,μ2H_},{σ1H_,σ2H_}, ρH_},{{μ1D_,μ2D_},{σ1D_,σ2D_}, ρD_}]:=
1-CDF[BinormalDistribution[{μ1D, μ2D}, {σ1D,σ2D}, ρD],{InverseCDF[NormalDistribution[μ1D,σ1D],1-x1],InverseCDF[NormalDistribution[μ2D,σ2D],1-x2]}]

spec[{x1_,x2_},{{μ1H_,μ2H_},{σ1H_,σ2H_}, ρH_},{{μ1D_,μ2D_},{σ1D_,σ2D_}, ρD_}]:=
CDF[BinormalDistribution[{μ1H, μ2H},{σ1H,σ2H}, ρH],{InverseCDF[NormalDistribution[μ1H,σ1H],x1],InverseCDF[NormalDistribution[μ2H,σ2H],x2]}]

dppv[{x1_,x2_},{{μ1H_,μ2H_},{σ1H_,σ2H_}, ρH_},{{μ1D_,μ2D_},{σ1D_,σ2D_}, ρD_},pd_]:=(sens[{x1,x2},{{μ1H,μ2H},{σ1H,σ2H}, ρH},{{μ1D,μ2D},{σ1D,σ2D}, ρD}] pd)/(sens[{x1,x2},{{μ1H,μ2H},{σ1H,σ2H}, ρH},{{μ1D,μ2D},{σ1D,σ2D}, ρD}] pd+(1-specs[{x1,x2},{{μ1H,μ2H},{σ1H,σ2H}, ρH},{{μ1D,μ2D},{σ1D,σ2D}, ρD}])(1-pd));

dnpv[{x1_,x2_},{{μ1H_,μ2H_},{σ1H_,σ2H_}, ρH_},{{μ1D_,μ2D_},{σ1D_,σ2D_}, ρD_},pd_]:=(specs[{x1,x2},{{μ1H,μ2H},{σ1H,σ2H}, ρH},{{μ1D,μ2D},{σ1D,σ2D}, ρD}](1-pd))/(specs[{x1,x2},{{μ1H,μ2H},{σ1H,σ2H}, ρH},{{μ1D,μ2D},{σ1D,σ2D}, ρD}](1-pd)+(1-sens[{x1,x2},{{μ1H,μ2H},{σ1H,σ2H}, ρH},{{μ1D,μ2D},{σ1D,σ2D}, ρD}])pd);

dor[{x1_,x2_},{{μ1H_,μ2H_},{σ1H_,σ2H_},ρH_},{{μ1D_,μ2D_},{σ1D_,σ2D_},ρD_}]:=(((sens[{x1,x2},{{μ1H,μ2H},{σ1H,σ2H},ρH},{{μ1D,μ2D},{σ1D,σ2D},ρD}])/(1-sens[{x1,x2},{{μ1H,μ2H},{σ1H,σ2H},ρH},{{μ1D,μ2D},{σ1D,σ2D},ρD}]))/((1-specs[{x1,x2},{{μ1H,μ2H},{σ1H,σ2H}, ρH},{{μ1D,μ2D},{σ1D,σ2D}, ρD}])/(specs[{x1,x2},{{μ1H,μ2H},{σ1H,σ2H}, ρH},{{μ1D,μ2D},{σ1D,σ2D}, ρD}])));

dplr[{x1_,x2_},{{μ1H_,μ2H_},{σ1H_,σ2H_},ρH_},{{μ1D_,μ2D_},{σ1D_,σ2D_},ρD_}]:=sens[{x1,x2},{{μ1H,μ2H},{σ1H,σ2H},ρH},{{μ1D,μ2D},{σ1D,σ2D},ρD}]/(1-specs[{x1,x2},{{μ1H,μ2H},{σ1H,σ2H}, ρH},{{μ1D,μ2D},{σ1D,σ2D}, ρD}]);

dnlr[{x1_,x2_},{{μ1H_,μ2H_},{σ1H_,σ2H_},ρH_},{{μ1D_,μ2D_},{σ1D_,σ2D_},ρD_}]:=(1-sens[{x1,x2},{{μ1H,μ2H},{σ1H,σ2H},ρH},{{μ1D,μ2D},{σ1D,σ2D},ρD}])/specs[{x1,x2},{{μ1H,μ2H},{σ1H,σ2H}, ρH},{{μ1D,μ2D},{σ1D,σ2D}, ρD}];

hppv[{x1_,x2_},{{μ1H_,μ2H_},{σ1H_,σ2H_}, ρH_},{{μ1D_,μ2D_},{σ1D_,σ2D_}, ρD_},pd_]:=(senss[{x1,x2},{{μ1H,μ2H},{σ1H,σ2H},ρH},{{μ1D,μ2D},{σ1D,σ2D},ρD}]pd)/(senss[{x1,x2},{{μ1H,μ2H},{σ1H,σ2H},ρH},{{μ1D,μ2D},{σ1D,σ2D},ρD}]pd+(1-pd)(1-spec[{x1,x2},{{μ1H,μ2H},{σ1H,σ2H},ρH},{{μ1D,μ2D},{σ1D,σ2D},ρD}]))

hnpv[{x1_,x2_},{{μ1H_,μ2H_},{σ1H_,σ2H_}, ρH_},{{μ1D_,μ2D_},{σ1D_,σ2D_}, ρD_},pd_]:=spec[{x1,x2},{{μ1H,μ2H},{σ1H,σ2H},ρH},{{μ1D,μ2D},{σ1D,σ2D},ρD}](1-pd)/(spec[{x1,x2},{{μ1H,μ2H},{σ1H,σ2H},ρH},{{μ1D,μ2D},{σ1D,σ2D},ρD}](1-pd)+(pd(1-senss[{x1,x2},{{μ1H,μ2H},{σ1H,σ2H},ρH},{{μ1D,μ2D},{σ1D,σ2D},ρD}])))

hor[{x1_,x2_},{{μ1H_,μ2H_},{σ1H_,σ2H_},ρH_},{{μ1D_,μ2D_},{σ1D_,σ2D_},ρD_}]:=(((senss[{x1,x2},{{μ1H,μ2H},{σ1H,σ2H},ρH},{{μ1D,μ2D},{σ1D,σ2D},ρD}])/(1 - senss[{x1,x2},{{μ1H,μ2H},{σ1H,σ2H},ρH},{{μ1D,μ2D},{σ1D,σ2D},ρD}]))/((1 - spec[{x1,x2},{{μ1H,μ2H},{σ1H,σ2H},ρH},{{μ1D,μ2D},{σ1D,σ2D},ρD}])/(spec[{x1,x2},{{μ1H,μ2H},{σ1H,σ2H},ρH},{{μ1D,μ2D},{σ1D,σ2D},ρD}])))

hplr[{x1_,x2_},{{μ1H_,μ2H_},{σ1H_,σ2H_},ρH_},{{μ1D_,μ2D_},{σ1D_,σ2D_},ρD_}]:=(1/(1-spec[{x1,x2},{{μ1H,μ2H},{σ1H,σ2H},ρH},{{μ1D,μ2D},{σ1D,σ2D},ρD}]))senss[{x1,x2},{{μ1H,μ2H},{σ1H,σ2H},ρH},{{μ1D,μ2D},{σ1D,σ2D},ρD}]

hnlr[{x1_,x2_},{{μ1H_,μ2H_},{σ1H_,σ2H_},ρH_},{{μ1D_,μ2D_},{σ1D_,σ2D_},ρD_}]:=(1/spec[{x1,x2},{{μ1H,μ2H},{σ1H,σ2H},ρH},{{μ1D,μ2D},{σ1D,σ2D},ρD}])(1-senss[{x1,x2},{{μ1H,μ2H},{σ1H,σ2H},ρH},{{μ1D,μ2D},{σ1D,σ2D},ρD}])

Manipulate[
Which[
vs==0,
Which[
plot==-2,
Plot3D[Tooltip[sens[{x1,x2},{{μ1H,μ2H},{σ1H,σ2H},ρH},{{μ1D,μ2D},{σ1D,σ2D},ρD}],"CSens plot"],{x1,0.001,0.999},{x2,0.001,0.999},PlotRange->{Full,Full,Full},BoxRatios->{1,1,1}, ColorFunction->"DeepSeaColors",AxesLabel->{"sensitivity of \nfirst test","sensitivity of \nsecond test",""},PlotLabel->Row[{"sensitivity (CSens)"}],ImageSize->{350,375}],
plot==-1,
Plot3D[Tooltip[specs[{x1,x2},{{μ1H,μ2H},{σ1H,σ2H},ρH},{{μ1D,μ2D},{σ1D,σ2D},ρD}],"CSpec plot"],{x1,0.001,0.999},{x2,0.001,0.999},BoxRatios->{1,1,1}, PlotRange->{Full,Full,Full},ColorFunction->"DeepSeaColors",AxesLabel->{"sensitivity of \nfirst test","sensitivity of \nsecond test",""},PlotLabel->Row[{"specificity (CSpec)"}],ImageSize->{350,375}],
plot==0,
Plot3D[Tooltip[dppv[{x1,x2},{{μ1H,μ2H},{σ1H,σ2H},ρH},{{μ1D,μ2D},{σ1D,σ2D},ρD},pD],"PPV plot"],{x1,0.001,0.999},{x2,0.001,0.999},PlotRange->{Full,Full,Full}, BoxRatios->{1,1,1}, ColorFunction->"DeepSeaColors",AxesLabel->{"sensitivity of \nfirst test","sensitivity of \nsecond test",""},PlotLabel->Row[{"positive predictive value (PPV)"}],ImageSize->{350,375}],
plot==1,
Plot3D[Tooltip[dnpv[{x1,x2},{{μ1H,μ2H},{σ1H,σ2H},ρH},{{μ1D,μ2D},{σ1D,σ2D},ρD},pD],"NPV plot"],{x1,0.001,0.999},{x2,0.001,0.999},PlotRange->{Full,Full,Full}, BoxRatios->{1,1,1}, ColorFunction->"DeepSeaColors",AxesLabel->{"sensitivity of \nfirst test","sensitivity of \nsecond test",""},PlotLabel->Row[{"negative predictive value (NPV)"}],ImageSize->{350,375}],
plot==2,
Plot3D[Tooltip[dor[{x1,x2},{{μ1H,μ2H},{σ1H,σ2H},ρH},{{μ1D,μ2D},{σ1D,σ2D},ρD}],"OR plot"],{x1,0.001,0.999},{x2,0.001,0.999},BoxRatios->{1,1,1}, ColorFunction->"DeepSeaColors",AxesLabel->{"sensitivity of \nfirst test","sensitivity of \nsecond test",""},PlotLabel->Row[{"odds ratio (OR)"}],ImageSize->{350,375}],
plot==3,
Plot3D[Tooltip[dplr[{x1,x2},{{μ1H,μ2H},{σ1H,σ2H},ρH},{{μ1D,μ2D},{σ1D,σ2D},ρD}],"LR+ plot"],{x1,0.001,0.999},{x2,0.001,0.999},BoxRatios->{1,1,1}, ColorFunction->"DeepSeaColors",AxesLabel->{"sensitivity of \nfirst test","sensitivity of \nsecond test",""},PlotLabel->Row[{"likelihood ratio for a positive result (LR+)"}],ImageSize->{350,375}],
plot==4,
Plot3D[Tooltip[dnlr[{x1,x2},{{μ1H,μ2H},{σ1H,σ2H},ρH},{{μ1D,μ2D},{σ1D,σ2D},ρD}],"LR- plot"],{x1,0.001,0.999},{x2,0.001,0.999},BoxRatios->{1,1,1}, ColorFunction->"DeepSeaColors",AxesLabel->{"sensitivity of \nfirst test","sensitivity of \nsecond test",""},PlotLabel->Row[{"likelihood ratio for a negative result (LR-)"}],ImageSize->{350,375}]
],
vs==1,
Which[
plot==-2,
Plot3D[Tooltip[senss[{x1,x2},{{μ1H,μ2H},{σ1H,σ2H},ρH},{{μ1D,μ2D},{σ1D,σ2D},ρD}],"CSens plot"],{x1,0.001,0.999},{x2,0.001,0.999},PlotRange->{Full,Full,Full}, BoxRatios->{1,1,1}, ColorFunction->"DeepSeaColors",AxesLabel->{"specificity of \nfirst test","specificity of \nsecond test",""},PlotLabel->Row[{"sensitivity (CSens)"}],ImageSize->{350,375}],
plot==-1,
Plot3D[Tooltip[spec[{x1,x2},{{μ1H,μ2H},{σ1H,σ2H},ρH},{{μ1D,μ2D},{σ1D,σ2D},ρD}],"CSpec plot"],{x1,0.001,0.999},{x2,0.001,0.999},PlotRange->{Full,Full,Full}, BoxRatios->{1,1,1}, ColorFunction->"DeepSeaColors",AxesLabel->{"specificity of \nfirst test","specificity of \nsecond test",""},PlotLabel->Row[{"specificity (CSpec)"}],ImageSize->{350,375}],
plot==0,
Plot3D[Tooltip[hppv[{x1,x2},{{μ1H,μ2H},{σ1H,σ2H},ρH},{{μ1D,μ2D},{σ1D,σ2D},ρD},pD],"PPV plot"],{x1,0.001,0.999},{x2,0.001,0.999},PlotRange->{Full,Full,Full}, BoxRatios->{1,1,1}, ColorFunction->"DeepSeaColors",AxesLabel->{"specificity of \nfirst test","specificity of \nsecond test",""},PlotLabel->Row[{"positive predictive value (PPV)"}],ImageSize->{350,375}],
plot==1,
Plot3D[Tooltip[hnpv[{x1,x2},{{μ1H,μ2H},{σ1H,σ2H},ρH},{{μ1D,μ2D},{σ1D,σ2D},ρD},pD],"NPV plot"],{x1,0.001,0.999},{x2,0.001,0.999},PlotRange->{Full,Full,Full}, BoxRatios->{1,1,1}, ColorFunction->"DeepSeaColors",AxesLabel->{"specificity of \nfirst test","specificity of \nsecond test",""},PlotLabel->Row[{"negative predictive value (NPV)"}],ImageSize->{350,375}],
plot==2,
Plot3D[Tooltip[hor[{x1,x2},{{μ1H,μ2H},{σ1H,σ2H},ρH},{{μ1D,μ2D},{σ1D,σ2D},ρD}],"OR plot"],{x1,0.001,0.999},{x2,0.001,0.999},BoxRatios->{1,1,1}, ColorFunction->"DeepSeaColors",AxesLabel->{"specificity of \nfirst test","specificity of \nsecond test",""},PlotLabel->Row[{"odds ratio (OR)"}],ImageSize->{350,375}],
plot==3,
Plot3D[Tooltip[hplr[{x1,x2},{{μ1H,μ2H},{σ1H,σ2H},ρH},{{μ1D,μ2D},{σ1D,σ2D},ρD}],"LR+ plot"],{x1,0.001,0.999},{x2,0.001,0.999},BoxRatios->{1,1,1}, ColorFunction->"DeepSeaColors",AxesLabel->{"specificity of \nfirst test","specificity of \nsecond test",""},PlotLabel->Row[{"likelihood ratio for a positive result (LR+)"}],ImageSize->{350,375}],
plot==4,
Plot3D[Tooltip[hnlr[{x1,x2},{{μ1H,μ2H},{σ1H,σ2H},ρH},{{μ1D,μ2D},{σ1D,σ2D},ρD}],"LR- plot"],{x1,0.001,0.999},{x2,0.001,0.999},BoxRatios->{1,1,1}, ColorFunction->"DeepSeaColors",AxesLabel->{"specificity of \nfirst test","specificity of \nsecond test",""},PlotLabel->Row[{"likelihood ratio for a negative result (LR-)"}],ImageSize->{350,375}]
]
],
{{plot,0,"plot"},{-2->"CSens",-1->"CSpec",0->"PPV",1->"NPV",2->"OR",3->"LR+",4-> "LR-"},ControlPlacement->Top},
{{vs,0, "versus"},{0->"single test sensitivities",1->"single test specificities"},ControlPlacement->Top},
Style["prevalence of disease",Bold],
{{pD,0.05,""},0.00000001,.99,ImageSize->Tiny,Appearance->"Labeled"},
"",
Style["nondiseased population",Bold],
Delimiter,
"first test",
{{μ1H,0,"mean"},-6,6,.01,ImageSize->Tiny,Appearance->"Labeled"},
{{σ1H,1,"standard deviation"},0.01,6,.01,ImageSize->Tiny,Appearance->"Labeled"},
Delimiter,
"second test",
{{μ2H,0.5,"mean"},-6,6,.01,ImageSize->Tiny,Appearance->"Labeled"},
{{σ2H,0.7,"standard deviation"},0.01,6,.01,ImageSize->Tiny,Appearance->"Labeled"},
Delimiter,
{{ρH,0,"correlation coefficient"},-.99,.99,.01,ImageSize->Tiny,Appearance->"Labeled"},
Delimiter,
"",
Style["diseased population",Bold],
Delimiter,
"first test",
{{μ1D,3.5,"mean"},-6,6,.01,ImageSize->Tiny,Appearance->"Labeled"},
{{σ1D,1,"standard deviation"},0.01,6,.01,ImageSize->Tiny,Appearance->"Labeled"},
Delimiter,
"second test",
{{μ2D,2.5,"mean "},-6,6,.01,ImageSize->Tiny,Appearance->"Labeled"},
{{σ2D,0.8,"standard deviation"},0.01,6,.01,ImageSize->Tiny,Appearance->"Labeled"},
Delimiter,
{{ρD,0.3,"correlation coefficient"},-.99,.99,.01,ImageSize->Tiny,Appearance->"Labeled"},
Delimiter,"",
SaveDefinitions->True,AutorunSequencing->{1,2,6},TrackedSymbols->True,ControlPlacement->Left]

Description

• "CSens": sensitivity

• "CSpec": specificity

• "PPV": positive predictive value

• "NPV": negative predictive value

• "OR": (diagnostic) odds ratio

• "LR+": likelihood ratio for a positive result

• "LR-": likelihood ratio for a negative result

These measures are plotted against the sensitivities or the specificities of each single test. You can select them by clicking the respective "versus" button.

Snapshots

Details

Assume bivariate normal distributions for the paired measurements for each of the two tests on both nondiseased and diseased populations. The measures are used in evaluation of the clinical diagnostic accuracy of the combined diagnostic tests applied to a diseased or nondiseased population. They can be calculated as functions of the sensitivities or the specificities of each of the two tests.

Sensitivity of each single test is the fraction of the diseased population with a positive test result, while specificity is the fraction of the nondiseased population with a negative test result. Sensitivity of the two combined tests is the fraction of the diseased population with at least one positive test result, while specificity is the fraction of the nondiseased population with negative results for both tests. If we denote by CSens and CSpec the sensitivity and the specificity of the combined tests, and by pr the prevalence of the disease, we have:

PPV=((CSens×pr)/(CSens×pr+(1-CSpec)(1-pr))),

NPV=((CSpec(1-pr))/(CSpec(1-pr)+(1-CSens)pr)),

OR=(CSens/(1-CSens))/((1-CSpec)/CSpec),

LR+ =(CSens/(1-CSpec)),

LR- =((1-CSens)/CSpec).

This Demonstration is an extension of [1] and is appropriate as an educational tool for medical students and junior doctors.

References

[1] T. Chatzimichail. "Analysis of Diagnostic Accuracy Measures" from the Wolfram Demonstrations Project—A Wolfram Web Resource. Available at: demonstrations.wolfram.com/AnalysisOfDiagnosticAccuracyMeasures.

Keywords

sensitivity
specificity
diagnostic test
combined tests
diagnostic accuracy
normal distribution
bivariate normal distribution
positive predictive value
negative predictive value
likelihood ratio
odds ratio

Related Links

(HyperlinkDefault["Analysis of Diagnostic Accuracy Measures", demonstrations.wolfram.com/AnalysisOfDiagnosticAccuracyMeasures/, demonstrations.wolfram.com/AnalysisOfDiagnosticAccuracyMeasures/])

Disclaimer of Warranties

The notebook is provided “as is”, without warranty of any kind, express or implied, including but not limited to the warranties of merchantability, fitness for a particular purpose and noninfringement. In no event shall the authors or Hellenic Complex Systems Laboratory or any of its members be liable for any claim, damages or other liability, whether in an action of contract, tort or otherwise, arising from, out of or in connection with the notebook or the use or other dealings in the notebook.

About

Analysis of Diagnostic Accuracy Measures for Two Combined Diagnostic Tests
Version Number 1.1.0
Hellenic Complex Systems Laboratory 2021
First published at Wolfram Demonstrations Project at: (HyperlinkDefault["\!\(\*StyleBox[\"demonstrations\",FontFamily->\"Source Sans Pro ExtraLight\",FontSize->12,FontColor->RGBColor[0., 0.25098039215686274`, 0.5019607843137255]]\)\!\(\*StyleBox[\".\",FontFamily->\"Source Sans Pro ExtraLight\",FontSize->12,FontColor->RGBColor[0., 0.25098039215686274`, 0.5019607843137255]]\)\!\(\*StyleBox[\"wolfram\",FontFamily->\"Source Sans Pro ExtraLight\",FontSize->12,FontColor->RGBColor[0., 0.25098039215686274`, 0.5019607843137255]]\)\!\(\*StyleBox[\".\",FontFamily->\"Source Sans Pro ExtraLight\",FontSize->12,FontColor->RGBColor[0., 0.25098039215686274`, 0.5019607843137255]]\)\!\(\*StyleBox[\"com\",FontFamily->\"Source Sans Pro ExtraLight\",FontSize->12,FontColor->RGBColor[0., 0.25098039215686274`, 0.5019607843137255]]\)\!\(\*StyleBox[\"/\",FontFamily->\"Source Sans Pro ExtraLight\",FontSize->12,FontColor->RGBColor[0., 0.25098039215686274`, 0.5019607843137255]]\)\!\(\*StyleBox[\"AnalysisOfDiagnosticAccuracyMeasuresForTwoCombinedDiagnostic\",FontFamily->\"Source Sans Pro ExtraLight\",FontSize->12,FontColor->RGBColor[0., 0.25098039215686274`, 0.5019607843137255]]\)\!\(\*StyleBox[\"/\",FontFamily->\"Source Sans Pro ExtraLight\",FontSize->12,FontColor->RGBColor[0., 0.25098039215686274`, 0.5019607843137255]]\)", demonstrations.wolfram.com/AnalysisOfDiagnosticAccuracyMeasuresForTwoCombinedDiagnostic/, demonstrations.wolfram.com/AnalysisOfDiagnosticAccuracyMeasuresForTwoCombinedDiagnostic/])
The notebook is distributed under  an Attribution - NonCommercial - ShareAlike 4.0 International Creative Commons License.