The true incidence of COVID - 19

Seth J. Chandler 2020
There has been considerable controversy in the United States (and elsewhere) about the true incidence of COVID-19. The lack of certainty is significantly due to the difficulty in testing the entire relevant population. This notebook suggests an algebraic method for estimating the incidence in the entire population. Basically, the user inputs six facts: (1) the population of the nation in question (pop); (2) the number of tests conducted in the relevant time period (perhaps the period in which an individual may have the disease) (tested); (3) the sensitivity of the test used to detect the disease (sensitivity); (4) the specificity of the test used to detect the disease (specificity); (5) the fraction of persons with the disease who seek out testing (f) ; and (6) the fraction of tests coming back positive (pos). We now have six equations with six unknowns, which can yield an exact solution.
Here in fact is the code we need to solve the algebra problem, where tn are true negatives, fp are false positives, hu are healthy untested, fn are false negatives, tp and false positives and du are diseased untested.
In[]:=
soln=First@Solvetn+fp+hu+fn+tp+dupop,tn+fp+fn+tptested,
tp
tp+fn
sensitivity,
tn
tn+fp
specificity,
fn+tp
fn+tp+du
f,
fp+tp
tn+fp+fn+tp
pos,{tn,fp,hu,fn,tp,du}//FullSimplify
Out[]=
tn
(-pos+sensitivity)specificitytested
-1+sensitivity+specificity
,fp
(pos-sensitivity)(-1+specificity)tested
-1+sensitivity+specificity
,hupop+
(1+(-1+f)pos-fsensitivity-specificity)tested
f(-1+sensitivity+specificity)
,fn-
(-1+sensitivity)(-1+pos+specificity)tested
-1+sensitivity+specificity
,tp
sensitivity(-1+pos+specificity)tested
-1+sensitivity+specificity
,du-
(-1+f)(-1+pos+specificity)tested
f(-1+sensitivity+specificity)

Using this algebra, I create an interactive “Manipulate” that groups the population by actual disease state and by three possible results of the testing regime: tested negative, tested positive or untested. Certain combinations of the controls will lead to impossible results: the number of people in one of the cells being negative. When this impossibility occurs, the user is warned by having the background for the grid turn red.
In[]:=
ManipulatemakeGrid[pop,tested,sensitivity,specificity,f,pos],​​{{pop,325000000,"population"},1000000,1500000000,1000000,Appearance"Labeled"},​​{{tested,1000000,"tests conducted"},100000,3000000,10000,Appearance"Labeled"},​​{{sensitivity,0.9,"sensitivity"},0.5,1,0.01,Appearance"Labeled"},​​{{specificity,0.98,"specificity"},0.5,1,0.01,Appearance"Labeled"},​​{{f,0.25,"fraction of diseased that get tested"},0.01,0.99,0.01,Appearance"Labeled"},​​{{pos,0.23,"fractions of tests returning positive"},0.01,0.99,0.01,Appearance"Labeled"},BaseStyle14,LabelStyle14,SaveDefinitionsTrue,​​Initializationvalid[pop_,tested_,sensitivity_,specificity_,f_,pos_]:=
Or[
]
;gridDecorate=Labeled[Grid[#1/.n_?NumericQDecimalForm[Round[n],DigitBlock3],DividersAll,AlignmentRight,BackgroundIf[valid[pop,tested,sensitivity,specificity,f,pos],{{ColorData[42][2],{ColorData[42][1]}},{ColorData[42][3],{None}}},Red]],Style[StringTemplate["Ratio of tested positive to actually diseased is `1`;Ratio of actually diseased to tested positive is `2`"][#[[4,3]]/#[[3,5]],#[[3,5]]/#[[4,3]]],11]]&;makeGrid[pop_,tested_,sensitivity_,specificity_,f_,pos_]:=
With[
]
​​
Out[]=
​
population
325000000
tests conducted
1000000
sensitivity
0.9
specificity
0.98
fraction of diseased that get tested
0.25
fractions of tests returning positive
0.23
testednegative
testedpositive
untested
total
healthy
746,136
15,227
323,284,091
324,045,455
diseased
23,864
214,773
715,909
954,545
total
770,000
230,000
324,000,000
325,000,000
Ratio of tested positive to actually diseased is 0.240952;Ratio of actually diseased to tested positive is 4.1502
For the default values, this would suggest that although there were 230,000 people who tested positive during the relevant time period (of whom 214,773 really were diseased), in fact there are 954,545 actively infected persons in the nation so that the ratio of actual disease to positive tests is about 4.15. This value is lower than that computed by a leading insurance modeler, AIR, which recently estimated that there were upwards of 5 million cases of COVID-19 in the United States whereas the Johns Hopkins total of confirmed cases as of April 17, 2020, is about 680,000. To get the data to line up with the AIR model, one can assume that only about 6% of those who are diseased are getting tested and that the sensitivity of the test is only about 0.7.

References

Data on the fraction of tests positive and the fraction of tests conducted may be found here : https : // www.wolframcloud.com/obj/examples/COVID19Resources
The following websites contain information on the sensitivity and specificity of COVID - 19 testing.
◼
  • https : // www.asianscientist.com/2020/04/features/covid - 19 - diagnostics - explained/ (claims the PCR-RT test has sensitivity and specificity of at least 90%)
  • ◼
  • https://pubs.rsna.org/doi/pdf/10.1148/radiol.2020200823 (identifies various sensitivity and specificity rates for tests based on chest x-rays)
  • ◼
  • https : // www.advisory.com/daily - briefing/2020/04/06/false - negative (claims sensitivity may be as low as 70%)
  • Notes

    Although there is no authoritative data on the specificity of current tests – and, of course it may vary over the panoply of tests currently deployed – data from New Zealand suggests that the tests in use there have a very high rate of specificity, perhaps as high as 1.0.
    The derivation to determine whether the values for the sliders yield impermissible results is set forth below:
    In[]:=
    constraint1=Reduce
    (-pos+sensitivity)specificitytested
    -1+sensitivity+specificity
    ≥0,0≤pos≤1,0≤sensitivity≤1,0<=specificity≤1,0<=tested,{pos,sensitivity,specificity,tested},Reals//FullSimplify;
    In[]:=
    constraint2=Reduce
    (pos-sensitivity)(-1+specificity)tested
    -1+sensitivity+specificity
    ≥0,0≤pos≤1,0≤sensitivity≤1,0<=specificity≤1,0<=tested,{pos,sensitivity,specificity,tested},Reals//FullSimplify;
    In[]:=
    constraint3=Reducepop+
    (1+(-1+f)pos-fsensitivity-specificity)tested
    f(-1+sensitivity+specificity)
    ≥0,0≤pos≤1,0≤sensitivity≤1,0<=specificity≤1,0<=tested,0≤f≤1,pop≥0,{pos,sensitivity,specificity,tested,pop,f},Reals//FullSimplify;
    In[]:=
    constraint4=Reduce-
    (-1+sensitivity)(-1+pos+specificity)tested
    -1+sensitivity+specificity
    ≥0,0≤pos≤1,0≤sensitivity≤1,0<=specificity≤1,0<=tested,{pos,sensitivity,specificity,tested},Reals//FullSimplify;
    In[]:=
    constraint5=Reduce
    sensitivity(-1+pos+specificity)tested
    -1+sensitivity+specificity
    ≥0,0≤pos≤1,0≤sensitivity≤1,0<=specificity≤1,0<=tested,{pos,sensitivity,specificity,tested},Reals//FullSimplify;
    In[]:=
    constraint6=Reduce-
    (-1+f)(-1+pos+specificity)tested
    f(-1+sensitivity+specificity)
    ≥0,0≤pos≤1,0≤sensitivity≤1,0<=specificity≤1,0<=tested,0≤f≤1,pop≥0,{pos,sensitivity,specificity,tested,pop,f},Reals//FullSimplify;
    In[]:=
    constrained=Reduce[constraint1&&constraint2&&constraint3&&constraint4&&constraint5&&constraint6,{pos,sensitivity,specificity,tested,pop,f}];
    In[]:=
    constrained//FullSimplify
    Out[]=
    tested>0&&(f1&&poptested&&((specificity≥0&&((sensitivity0&&((pos0&&specificity<1)||(pos>0&&pos<1&&pos+specificity<1)))||(pos>0&&pos<1&&((possensitivity&&sensitivity+specificity<1)||(sensitivity>0&&sensitivity<pos&&pos+specificity<1)))))||(specificity≤1&&((sensitivity1&&((pos1&&specificity>0)||(pos+specificity>1&&pos>0&&pos<1)))||(pos>0&&pos<1&&((possensitivity&&sensitivity+specificity>1)||(pos+specificity>1&&pos<sensitivity&&sensitivity<1)))))))||pop>tested&&f≤1&&
    tested
    pop
    ≤f&&((pos0&&sensitivity0&&specificity<1&&specificity≥0)||(pos1&&sensitivity1&&specificity>0&&specificity≤1))||pos>0&&pos<1&&
    (-1+pos+specificity)tested
    pop(-1+sensitivity+specificity)+(pos-sensitivity)tested
    ≤f&&((possensitivity&&((specificity≥0&&sensitivity+specificity<1)||(sensitivity+specificity>1&&specificity≤1)))||(specificity≥0&&sensitivity>0&&sensitivity<pos&&pos+specificity<1)||(pos+specificity>1&&pos<sensitivity&&sensitivity<1&&specificity≤1))||sensitivity0&&specificity≥0&&pos+specificity<1&&
    (-1+pos+specificity)tested
    pop(-1+specificity)+postested
    ≤f||sensitivity1&&specificity≤1&&pos+specificity>1&&
    (-1+pos+specificity)tested
    popspecificity+(-1+pos)tested
    ≤f||(f>0&&f≤1&&((pop≥tested&&tested≥0&&((sensitivity>0&&((pos0&&sensitivity≤1&&specificity1)||(pos<1&&pos>0&&pos>sensitivity&&pos+specificity1)))||(sensitivity<1&&((pos1&&sensitivity≥0&&specificity0)||(pos<1&&pos>0&&pos<sensitivity&&pos+specificity1)))||(pos<1&&pos>0&&pos+specificity1&&(sensitivity0||sensitivity1))))||(pop≥0&&tested0&&((pos0&&((sensitivity<1&&sensitivity>0&&(specificity0||(specificity<1&&sensitivity+specificity>1)||(specificity>0&&sensitivity+specificity<1)))||(specificity<1&&((sensitivity0&&specificity≥0)||(sensitivity1&&specificity>0)))))||(pos1&&((sensitivity<1&&sensitivity>0&&(specificity1||(specificity<1&&sensitivity+specificity>1)||(specificity>0&&sensitivity+specificity<1)))||(specificity>0&&((sensitivity0&&specificity<1)||(sensitivity1&&specificity≤1)))))||(pos<1&&pos>0&&((possensitivity&&((specificity≥0&&sensitivity+specificity<1)||(sensitivity+specificity>1&&specificity≤1)))||(sensitivity0&&((specificity≥0&&pos+specificity<1)||(pos+specificity>1&&specificity<1)))||(sensitivity1&&((specificity>0&&pos+specificity<1)||(pos+specificity>1&&specificity≤1)))||(pos<sensitivity&&sensitivity<1&&(specificity0||(sensitivity+specificity>1&&pos+specificity<1)||(specificity>0&&sensitivity+specificity<1)||(pos+specificity>1&&specificity≤1)))||(pos>sensitivity&&sensitivity>0&&(specificity1||(specificity≥0&&pos+specificity<1)||(sensitivity+specificity>1&&specificity<1)||(pos+specificity>1&&sensitivity+specificity<1)))))))))