## Off by 50 or off by 10?

| Gabriel |

Via MR, the NY Times has an article noting that two models of swine flu drastically under-estimated the spread of the epidemic. It notes that the actual number of American cases is something like 100,000 but the estimates were about 2,000. The natural inference is to think that they were off by a laughably wild factor of 50. However this just shows how hard it is to think about nonlinearity. The authors of the original predictions blamed the error on an underestimate of the number of infections seeding the system.

This sounds very plausible to me and in fact I can demonstrate just how sensitive contagion models are to such assumptions as the number of seed values. Here’s a graph of two contagions. Although the assumptions vary by an order of magnitude, they diverge by even more.

Here’s are some of the simplifying assumptions:

• the diffusion follows a Bass model
• after the intial cases there are no exogenous infections (e.g., from foreign travel)
• the population is homogenous population with no network structure

Here’s the Stata code so anyone with a copy of Stata should be able to replicate this and even fiddle with the parameters.

```capture program drop bassproject
program define bassproject
set more off
syntax anything(name=commandinput) [, graphoff nosave]
local match=regexm("`commandinput'","a ?\(([^\)]+)\) ?")
if `match'==1 {
local a=regexs(1)
}
else {
local a=0
}
local match=regexm("`commandinput'","b ?\(([0-9]*\.?[0-9]*)\) ?")
if `match'==1 {
local b=regexs(1)
}
else {
local b=0
}
local match=regexm("`commandinput'","[nN]?max ?\(([0-9]*\.?[0-9]*)\) ?")
if `match'==1 {
local nmax=regexs(1)
}
else {
local nmax=1
}
local match=regexm("`commandinput'","seed ?\(([0-9]*\.?[0-9]*)\) ?")
if `match'==1 {
local seed=regexs(1)
}
else {
local seed=0.01
}
local match=regexm("`commandinput'","periods ?\(([0-9]*\.?[0-9]*)\) ?")
if `match'==1 {
local periods=regexs(1)
}
else {
local periods=20
}
local match=regexm("`commandinput'","modeln?a?m?e? ?\(([^\)]+)\)")
if `match'==1 {
local modelname=regexs(1)
}
else {
local model="model"
}
disp "model named(`modelname')."
disp "delta_Nt=(`a' + `b' * Nt) * (`nmax' - Nt)"
disp "projected over `periods' spells with N_0=`seed'"
preserve
clear
set obs `periods'
quietly gen t=[_n]-1
quietly gen Nt=.
quietly gen deltan=.
quietly replace Nt=`seed' in 1
quietly replace deltan=(`a' + (`b' * Nt)) * (`nmax' - Nt) in 1
forvalues period=2/`periods' {
quietly replace Nt=Nt[_n-1]+deltan[_n-1] in `period'
quietly replace deltan=(`a' + (`b' * Nt)) * (`nmax' - Nt) in `period'
}
sort t
ren Nt nt_`modelname'
drop deltan
if "`nosave'"~="nosave" {
save projection_`modelname', replace
}
if "`graphoff'"~="graphoff" {
twoway (line nt_`modelname' t, lwidth(thick)), ytitle(Saturation to Date) xtitle(Time) /* ylabel(none, nolabels)  xlabel(none, nolabels) */
graph export projection_`modelname'.png, replace
}
clear
restore
end

cd ~/Documents/codeandculture/blackswine
*the assumptions go in the following two lines. aside from periods, all #s should be between 1 and 0
bassproject a(0) b(.5) seed(.00001) nmax(1) periods (20) model(smallseed)
bassproject a(0) b(.5) seed(.0001) nmax(1) periods (20) model(bigseed)

use projection_bigseed.dta, clear
append using projection_smallseed
lab var nt_bigseed "Assume many seed"
lab var nt_smallseed "Assume few seed"
twoway (line nt_bigseed t, lwidth(thick)) (line nt_smallseed t, lwidth(thick)), ytitle(Saturation to Date) xtitle(Time) /* ylabel(none, nolabels)  xlabel(none, nolabels) */
graph export projection_pooled.png, replace```