Loading...

COVID-19

This example uses the covid19 dataset to predict the number of deaths and cases one day in advance.

  • date: Date of the record.

  • cases: Number of people infected.

  • deaths: Number of deaths.

  • state: State.

  • fips: The Federal Information Processing Standards (FIPS) code for the county.

  • county: County.

We will follow the data science cycle (Data Exploration - Data Preparation - Data Modeling - Model Evaluation - Model Deployment) to solve this problem.

Initialization

This example uses the following version of vastorbit:

import vastorbit as vo

vo.__version__

Connect to VAST. This example uses an existing connection called VASTDSN. For details on how to create a connection, see the Connection tutorial. You can skip the below cell if you already have an established connection.

vo.connect("VASTDSN")

Let’s create a VastFrame of the dataset. The dataset is available here.

from vastorbit.datasets import load_commodities

covid19 = vo.read_csv("deaths.csv")
covid19
📅
date
Date
100%
Abc
county
Varchar(50)
100%
Abc
state
Varchar(50)
100%
123
fips
Integer
98%
123
cases
Integer
100%
123
deaths
Integer
100%
12020-03-12VolusiaFlorida1212730
22020-03-12WakeNorth Carolina3718380
32020-03-12Walla WallaWashington5307110
42020-03-12WardNorth Dakota3810110
52020-03-12WashingtonOregon41067100
62020-03-12WashingtonUtah4905310
72020-03-12WashoeNevada3203120
82020-03-12WashtenawMichigan2616120
92020-03-12WaukeshaWisconsin5513310
102020-03-12WayneMichigan2616310
112020-03-12WaynePennsylvania4212710
122020-03-12WeberUtah4905710
132020-03-12WestchesterNew York361191470
142020-03-12WhatcomWashington5307310
152020-03-12WilliamsonTennessee4718780
162020-03-12WorcesterMassachusetts2502720
172020-03-12WyandotteKansas2020911
182020-03-12YakimaWashington5307720
192020-03-12YoloCalifornia611310
202020-03-13AdaIdaho1600110

Data Exploration and Preparation

Let’s explore the data by displaying descriptive statistics of all the columns.

covid19.describe(method = "categorical", unique = True)
dtypecounttoptop_percentunique
"date"date1297472020-05-092.244110.0
"county"varchar(50)129747Washington1.151713.0
"state"varchar(50)129747Texas6.63355.0
"fips"integer128256[null]1.1492882.0
"cases"integer129747113.3033903.0
"deaths"integer129747060.989851.0

We have data from January 2020 to the beginning of May.

covid19["date"].describe()
value
name"date"
dtypedate
count129747
min2020-01-21
max2020-05-09

We’ll try to predict the number of future deaths by using the statistics from previous days. We can drop the columns county and fips, since the scope of our analysis is focused on the United States and the FIPS code isn’t relevant to our predictions.

covid19.drop(["fips", "county"])
📅
date
Date
100%
Abc
state
Varchar(50)
100%
123
cases
Integer
100%
123
deaths
Integer
100%
12020-03-12Florida30
22020-03-12North Carolina80
32020-03-12Washington10
42020-03-12North Dakota10
52020-03-12Oregon100
62020-03-12Utah10
72020-03-12Nevada20
82020-03-12Michigan20
92020-03-12Wisconsin10
102020-03-12Michigan10
112020-03-12Pennsylvania10
122020-03-12Utah10
132020-03-12New York1470
142020-03-12Washington10
152020-03-12Tennessee80
162020-03-12Massachusetts20
172020-03-12Kansas11
182020-03-12Washington20
192020-03-12California10
202020-03-13Idaho10

Let’s sum the number of deaths and cases by state and date.

import vastorbit.sql.functions as fun

covid19 = covid19.groupby(
    [
        "state",
        "date",
    ],
    [
        fun.sum(covid19["deaths"])._as("deaths"),
        fun.sum(covid19["cases"])._as("cases"),
    ],
)
covid19.head(10)
Abc
state
Varchar(50)
100%
📅
date
Date
100%
123
deaths
Bigint
100%
123
cases
Bigint
100%
1District of Columbia2020-04-231393361
2Massachusetts2020-04-23236046023
3Pennsylvania2020-05-09379358661
4Virginia2020-05-0982723196
5New York2020-04-1615669225761
6Indiana2020-04-164779542
7Kansas2020-04-16801595
8Kentucky2020-04-161322494
9Massachusetts2020-04-16124532181
10Florida2020-04-1772524745

Let’s look at the autocorrelation graphic of the number of deaths.

covid19.acf(
    column = "deaths",
    ts = "date",
    by = ["state"],
    p = 24,
)

The process doesn’t seem to be stationary. Let’s use a Dickey-Fuller test to confirm our hypothesis.

from vastorbit.machine_learning.model_selection.statistical_tests import adfuller

adfuller(
    covid19,
    ts = "date",
    column = "deaths",
    by = ["state"],
    p = 12,
)
value
ADF Test Statistic0.02032251874539726
p_value0.9837874324401557
# Lags used12
# Observations Used3039
Critical Value (1%)-3.43
Critical Value (2.5%)-3.12
Critical Value (5%)-2.86
Critical Value (10%)-2.57
Stationarity (alpha = 1%)False

We can look at the cumulative number of deaths and its exponentiality.

covid19["deaths"].plot(
    ts = "date",
    by = "state",
)

Let’s plot this for the entire country.

covid = covid19.groupby(
    ["date"],
    [fun.sum(covid19["deaths"])._as("deaths")],
)
covid["deaths"].plot(ts = "date")

As you would expect, there’s a clear correlation between the number of people infected and the number of deaths.

covid19.corr(["deaths", "cases"])

A vector autoregression (VAR) model can be very good to do the predictions. But first, let’s encode the states to look at their influence.

covid19["state"].one_hot_encode()
Abc
state
Varchar(50)
100%
📅
date
Date
100%
123
deaths
Bigint
100%
123
cases
Bigint
100%
123
state_Alabama
Bool
100%
123
state_Alaska
Bool
100%
123
state_Arizona
Bool
100%
123
state_Arkansas
Bool
100%
123
state_California
Bool
100%
123
state_Colorado
Bool
100%
123
state_Connecticut
Bool
100%
123
state_Delaware
Bool
100%
123
state_District_of_Columbia
Bool
100%
123
state_Florida
Bool
100%
123
state_Georgia
Bool
100%
123
state_Guam
Bool
100%
123
state_Hawaii
Bool
100%
123
state_Idaho
Bool
100%
123
state_Illinois
Bool
100%
123
state_Indiana
Bool
100%
123
state_Iowa
Bool
100%
123
state_Kansas
Bool
100%
123
state_Kentucky
Bool
100%
123
state_Louisiana
Bool
100%
123
state_Maine
Bool
100%
...
123
state_Nevada
Bool
100%
123
state_New_Hampshire
Bool
100%
123
state_New_Jersey
Bool
100%
123
state_New_Mexico
Bool
100%
123
state_New_York
Bool
100%
123
state_North_Carolina
Bool
100%
123
state_North_Dakota
Bool
100%
123
state_Northern_Mariana_Islands
Bool
100%
123
state_Ohio
Bool
100%
123
state_Oklahoma
Bool
100%
123
state_Oregon
Bool
100%
123
state_Pennsylvania
Bool
100%
123
state_Puerto_Rico
Bool
100%
123
state_Rhode_Island
Bool
100%
123
state_South_Carolina
Bool
100%
123
state_South_Dakota
Bool
100%
123
state_Tennessee
Bool
100%
123
state_Texas
Bool
100%
123
state_Utah
Bool
100%
123
state_Vermont
Bool
100%
123
state_Virgin_Islands
Bool
100%
123
state_Virginia
Bool
100%
123
state_Washington
Bool
100%
123
state_West_Virginia
Bool
100%
123
state_Wisconsin
Bool
100%
1Tennessee2020-03-2861363000000000000000000000...0000000000000000100000000
2New York2020-03-2893553517000000000000000000000...0000100000000000000000000
3West Virginia2020-03-280113000000000000000000000...0000000000000000000000010
4Oklahoma2020-03-2916429000000000000000000000...0000000001000000000000000
5Massachusetts2020-03-29484955000000000000000000000...0000000000000000000000000
6Louisiana2020-04-012796424000000000000000000010...0000000000000000000000000
7Nebraska2020-04-015226000000000000000000000...0000000000000000000000000
8New Hampshire2020-03-261158000000000000000000000...0100000000000000000000000
9Delaware2020-03-261143000000010000000000000...0000000000000000000000000
10Virgin Islands2020-03-26017000000000000000000000...0000000000000000000010000
11Montana2020-03-271121000000000000000000000...0000000000000000000000000
12North Carolina2020-04-12864520000000000000000000000...0000010000000000000000000
13North Dakota2020-04-128308000000000000000000000...0000001000000000000000000
14Connecticut2020-04-1255412035000000100000000000000...0000000000000000000000000
15Alaska2020-04-126270010000000000000000000...0000000000000000000000000
16North Carolina2020-04-13914788000000000000000000000...0000010000000000000000000
17Nevada2020-04-131143036000000000000000000000...1000000000000000000000000
18Illinois2020-03-30845125000000000000001000000...0000000000000000000000000
19Oregon2020-03-3016607000000000000000000000...0000000000100000000000000
20Michigan2020-04-29367040361000000000000000000000...0000000000000000000000000

Because of the upward monotonic trend, we can also look at the correlation between the days elapsed and the number of cases.

covid19["elapsed_days"] = covid19["date"] - fun.min(covid19["date"])._over(by = [covid19["state"]])
covid19["elapsed_days"] = "EXTRACT(DAY FROM {})"

We can generate the SQL code of the VastFrame to see what happens behind the scenes when we modify our data from within the VastFrame.

print(covid19.current_relation())

The VastFrame memorizes all of our operations on the data to dynamically generate the correct SQL statement and passes computation and aggregation to VAST.

Let’s see the correlation between the number of deaths and the other variables.

covid19.corr(focus = "deaths")

We can see clearly a high correlation for some variables. We can use them to compute a SARIMAX model, but we’ll stick to a VAR model for this study.

Let’s compute the total number of deaths and cases to create our VAR model.

covid19 = vo.read_csv("deaths.csv").groupby(
    ["date"],
    [
        fun.sum(covid19["deaths"])._as("deaths"),
        fun.sum(covid19["cases"])._as("cases"),
    ],
).search("date > CAST('2020-01-04' AS DATE)")

Machine Learning

Let’s create a VAR model to predict the number of COVID-19 deaths and cases in the USA.

from vastorbit.machine_learning.vast.tsa import VAR

model = VAR(p = 3)
model.fit(
    covid19,
    ts = "date",
    y = ["cases", "deaths"],
    return_report = True,
)
model.score(start = 20)
"cases""deaths"
r20.82079046739036470.8604025086316581

Our model is not bad. Let’s predict the number of deaths in a near future.

Cases:

model.plot(
    covid19,
    npredictions = 100,
    idx = 0,
    method="forecast",
)

Deaths:

model.plot(
    covid19,
    npredictions = 100,
    idx = 1,
    method="forecast",
)

The model performs well but may be somewhat unstable. To improve it, we could apply data preparation techniques, such as seasonal decomposition, before building the VAR model.

Conclusion

We’ve solved our problem in a pandas-like way, all without ever loading data into memory!