Skip to main content

Social Distancing and Hospital Capacity for Coronavirus

Social Distancing and Hospital Capacity for coronavirus

There was a great Washington Post article on social distancing. It comes with simulations to show you the effect of different measures, and I think it's fantastic #SciCom. I want to talk it over with my kids, but I want to be ready for them to ask questions like "what if we did (some cool other idea) for social distancing?" I also thought this would be useful for classes like intro physics, data science, computational modeling, etc., especially if those classes can team up with humanities, arts, etc. So, I want to have some Python code to replicate it and play with.

I put the Python code on github so that it's easy to grab and play with. I like having notebooks as standalone things, so all of the relevant code from when I wrote this up is also at the end of the notebook. I tried to make the code basic enough that it's easy to add different models yourself; please do so!

After poking at this, my main thought is that we'd be best off flattening the curve for as long as society can stand, while pushing hard at capacity and cures.

I'm no epidemiologist, but I think the results below make sense. The b

In [1]:
from matplotlib import pyplot as plt
from IPython.display import HTML
import imp
In [ ]:
from covid import social_distancing
from covid.social_distancing import Universe, getanim, draw_stacked_plot

This is all based on a classic model called the SIR model, in which people can either be "succeptible" to getting the disease (S), "infected" (I), or "recovered" (R). Recovered people are considered immune from the disease

There are lots of modifications you can make to that model, and you can google for them.

Let's start with a model like the one in the Washington Post article: a town of about 200 people that starts with one or two sick people. How long does it take for everyone to get infected? How long for everyone to recover?

Here's a first pass at it. Each person is represented by a dot. The blue dots are healthy (S for "succeptible") people. The red dots are sick people (I), and the green dots are recovered (R) people.

We'll make one change from the Washington Post model right from the beginning: if you get sick, there's a chance you'll die. Figuring out that chance is tricky, but it seems like 2% is a good estimate. So the dots will turn dark blue when people die.

In [3]:
npeople, nsteps = 200, 400
initial_infection_chance = 1.5/200
In [71]:
%%capture
u = Universe(npeople,
             initial_infection_chance=initial_infection_chance,
            )
u.run(nsteps)
anim0 = getanim(u,show_capacity=False)
In [72]:
u.data.i[0],u.data.d[-10:]
Out[72]:
(2.0, array([5., 5., 5., 5., 5., 5., 5., 5., 5., 5.]))
In [73]:
HTML(anim0.to_html5_video())
Out[73]:

(In case it's not obvious in your browser, that thing above is a movie. If you hover over it, you should have a button to play it. All of the plots that look like it below are also movies.)

You probably notice two things:

Basically everyone gets infected.

That red shape is the curve people talk about when they say #FlattenTheCurve.

It doesn't look like a lot of people died.

You can barely see the dark blue bit showing up at the top of the plot. If you look at the dots, you might not even have noticed the five dots that turned dark blue and stopped moving. But those five dots represent 2.5% of the population. If we scale this model up to the US population of 330 million, 2.5% is 8.5 million people dead!

Luckily, this model probably doesn't scale up perfectly to the whole US. But that's a worst case scenario of "what if we did nothing" and it's terrible.

Social Distancing

So what can we do? One idea is social distancing or social isolation. That's the idea that you just stay at home and don't interact with people. How much can that help? Let's follow the Washington Post article and see what happens if 25% of people isolate.

In [80]:
%%capture
u = Universe(npeople,distancing=0.25,
             initial_infection_chance=initial_infection_chance,
            )
u.run(nsteps)
anim25 = getanim(u,show_capacity=False)
In [81]:
u.data.i[0],u.data.d[-10:]
Out[81]:
(1.0, array([5., 5., 5., 5., 5., 5., 5., 5., 5., 5.]))
In [82]:
HTML(anim25.to_html5_video())
Out[82]: