Forecasting Deaths From COVID-19 in North Carolina up to the End of 2020
By: Ali Alsous
Tags: Covid 19, Python, Regression, Data Visualization, Data Science

Updating the model with new data

Here’s the entire Jupyter Notebook containing all code and previous model estimations

After downloading the data from the NC DHHS, I cleaned it to only include days after the first death from COVID-19 was recorded in NC on March 25th this year. I then load it in using the Pandas library.

# Loading in most recent data updated as of today Nov. 3rd



NCcovidNew = pd.read_excel('NCcovidNew.xlsx', sheet_name='Sheet 1')

Next, we assign our X and Y variables, in this case, date and deaths, and then reshape our data as needed.

date = NCcovidNew['Date']

y = NCcovidNew['NC Deaths']

date.shape # 224 days of data # Reshpaing the data



x=np.linspace(224,1,224)

x=np.reshape(x,(224,1))

y=np.array(y)

y=np.reshape(y,(224,1))

Refitting the model

Scikit-learn makes linear regression simple to implement with the following:

reg = linear_model.LinearRegression() # Constructing SKlearn model

reg.fit()

Yep, that's it. However, since our model will be a 2nd order polynomial regression taking the form h(x)=a+bx+cx², we need to assign a polynomial feature term that takes degree=2 as one of its arguments. The following code encompasses the entirety of the model.

poly_f=PolynomialFeatures(degree=2,include_bias=False) # Instantiating quadratic term X_poly=poly_f.fit_transform(x) # Applying quadratic transformation reg.fit(X_poly,y) # Fitting transformed data to model # Assigning variables to the model's parameter estimates a=reg.intercept_[0]

b=reg.coef_[0][0]

c=reg.coef_[0][1] print(“a (Intercept term) =”,a)

print(“b (Coefficient 1) =”,b)

print(“c (Coefficient 2) =”,c)

Here are the model’s parameter estimates:

a (Intercept term) = -64.88491059525245

b (Coefficient 1) = 10.06007469864205

c (Coefficient 2) = 0.04522201123331129

Putting it all together

Using Matplotlib once again, let's plot the data for daily deaths as a scatter plot and then overlay the data with our model’s forecast for the next 58 days leading up to December 31st.

plt.figure(figsize=(14,14))

plt.scatter(x,y) x=np.linspace(282,1,282)

x=np.reshape(x,(282,1))

plt.xlim(0, 290)

plt.ylim(0,8000) plt.plot(x, a + b*x+c*np.power(x,2), "r") plt.title('Predicted vs Actual COVID-19 Deaths in NC')

plt.xlabel('Days since first recorded death')

plt.ylabel('Deaths') plt.axvline(x=224+58,color='b') # Blue vertical line corresponds with Dec. 31st

plt.axhline(y=a + b*(224+58) + c*(224+58)**2,color='b')

plt.axhline(y=a + b*(224) + c*(224)**2,color='g') # Corresponds with today's death total of 4,457

The model, a simple quadratic equation, fits the data quite well. The vertical and horizontal green lines correspond with today's date, November 3rd, and death count of 4457. The blue lines correspond with December 31st’s date and predicted death count. So what is the predicted death count on 2020’s final day?

Prediction

In order to predict deaths by December 31st, we need to plug in the corresponding x-value into our model which takes the form of h(x)=a+bx+cx². The following code accomplishes this:

deathsByNewYears = a + b*(224+58) + c*(224+58)**2 # Forecasting 58 days into the future from today print("Predicted number of deaths on Dec. 31st:",int(deathsByNewYears))

And the output:

Predicted number of deaths on Dec. 31st: 6368

The model estimates 1,911 more deaths from COVID-19 will occur in the 58 days between today and the year’s end, culminating in 6,368 deaths on 2020's final day. Some future improvements that I’d like to make include calculating and displaying shaded confidence intervals in order to provide a true probabilistic forecast rather than an extrapolation of a simple curve. Likewise, I’d also like to create a dashboard for the model so that it automatically updates its parameter estimates and forecasts as new data is uploaded to the NC DHHS and then fed into the model.

Take this all with a grain of salt

To be clear, I’m not an epidemiologist nor an expert of any kind for that matter, but I do have a passion for data and storytelling. As for the model’s prediction, my overly optimistic gut feeling is that the true death total won’t eclipse 6000 by year’s end, but I wouldn’t bet the farm on it.

Globally, the virus is on a renewed tear, prompting many European nations to reinstate ‘wave-breaking’ shutdowns upon breaking previous records for new cases. In the U.S. new data are increasingly pointing towards a bleak winter as in the last two weeks records for the daily number of new cases have been set and shattered on successive days, most recently last Friday, when 98,500 infections were reported. President Trump also recently suggested at a campaign rally that he would fire Dr. Fauci after the election.

The key figure to watch for is hospitalizations since hospitals see seasonal increases in patients admitted in the winter due to the seasonality of the Flu. Hospitals already dealing with seasonal increases in patients may become overwhelmed in the face of widespread revived coronavirus outbreaks. Unfortunately, hospitalizations have been marching higher since the end of September and show little sign of letting up.