Loading...

COVID-19

This example uses the covid19 dataset to predict the number of deaths and cases one day in advance. You can download the Jupyter Notebook of the study here.

  • 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 VerticaPy:

import verticapy as vp

vp.__version__
Out[2]: '1.1.0'

Connect to Vertica. This example uses an existing connection called VerticaDSN. 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.

vp.connect("VerticaDSN")

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

from verticapy.datasets import load_commodities

covid19 = vp.read_csv("deaths.csv")
covid19.head(10)

Data Exploration and Preparation

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

covid19.describe(method = "categorical", unique = True)
...
top_percent
unique
"date"...2.244110.0
"county"...1.151713.0
"state"...6.63355.0
"fips"...1.1492883.0
"cases"...13.3033903.0
"deaths"...60.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(48)
100%
123
deaths
Int
100%
12020-01-25...California0
22020-01-29...California0
32020-01-29...Washington0
42020-01-30...California0
52020-01-31...California0
62020-01-31...Arizona0
72020-02-01...Illinois0
82020-02-01...California0
92020-02-02...California0
102020-02-02...Washington0
112020-02-03...California0
122020-02-05...California0
132020-02-05...California0
142020-02-05...Washington0
152020-02-06...California0
162020-02-08...Illinois0
172020-02-08...California0
182020-02-08...Washington0
192020-02-09...Illinois0
202020-02-09...California0

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

import verticapy.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(48)
100%
...
123
deaths
Integer
100%
123
cases
Integer
100%
1Iowa...6424
2Indiana...6201
3South Carolina...1504917
4Hawaii...9497
5Idaho...441577
6Florida...231971
7Florida...126733683
8Utah...040
9Utah...323301
10Kansas...1334305

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 verticapy.machine_learning.model_selection.statistical_tests import adfuller

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

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"])
Out[3]: 0.980134457432841

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(48)
100%
...
📅
date
Date
100%
123
state_Wisconsin
Bool
100%
1North Dakota...2020-03-220
2Kentucky...2020-04-090
3Wisconsin...2020-05-051
4Nebraska...2020-03-250
5Colorado...2020-04-290
6Washington...2020-03-030
7Washington...2020-01-270
8District of Columbia...2020-03-100
9Puerto Rico...2020-04-290
10Iowa...2020-03-270
11New Hampshire...2020-04-070
12Tennessee...2020-04-110
13New Mexico...2020-04-200
14Georgia...2020-03-210
15Louisiana...2020-03-100
16Pennsylvania...2020-03-140
17Mississippi...2020-03-170
18Kentucky...2020-03-130
19Hawaii...2020-03-130
20Wyoming...2020-03-180

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"]])

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

print(covid19.current_relation())
(
   SELECT
     "state",
     "date",
     "deaths",
     "cases",
     DECODE("state_Alabama", 'Alabama', 1, 0) AS "state_Alabama",
     DECODE("state_Alaska", 'Alaska', 1, 0) AS "state_Alaska",
     DECODE("state_Arizona", 'Arizona', 1, 0) AS "state_Arizona",
     DECODE("state_Arkansas", 'Arkansas', 1, 0) AS "state_Arkansas",
     DECODE("state_California", 'California', 1, 0) AS "state_California",
     DECODE("state_Colorado", 'Colorado', 1, 0) AS "state_Colorado",
     DECODE("state_Connecticut", 'Connecticut', 1, 0) AS "state_Connecticut",
     DECODE("state_Delaware", 'Delaware', 1, 0) AS "state_Delaware",
     DECODE("state_District_of_Columbia", 'District of Columbia', 1, 0) AS "state_District_of_Columbia",
     DECODE("state_Florida", 'Florida', 1, 0) AS "state_Florida",
     DECODE("state_Georgia", 'Georgia', 1, 0) AS "state_Georgia",
     DECODE("state_Guam", 'Guam', 1, 0) AS "state_Guam",
     DECODE("state_Hawaii", 'Hawaii', 1, 0) AS "state_Hawaii",
     DECODE("state_Idaho", 'Idaho', 1, 0) AS "state_Idaho",
     DECODE("state_Illinois", 'Illinois', 1, 0) AS "state_Illinois",
     DECODE("state_Indiana", 'Indiana', 1, 0) AS "state_Indiana",
     DECODE("state_Iowa", 'Iowa', 1, 0) AS "state_Iowa",
     DECODE("state_Kansas", 'Kansas', 1, 0) AS "state_Kansas",
     DECODE("state_Kentucky", 'Kentucky', 1, 0) AS "state_Kentucky",
     DECODE("state_Louisiana", 'Louisiana', 1, 0) AS "state_Louisiana",
     DECODE("state_Maine", 'Maine', 1, 0) AS "state_Maine",
     DECODE("state_Maryland", 'Maryland', 1, 0) AS "state_Maryland",
     DECODE("state_Massachusetts", 'Massachusetts', 1, 0) AS "state_Massachusetts",
     DECODE("state_Michigan", 'Michigan', 1, 0) AS "state_Michigan",
     DECODE("state_Minnesota", 'Minnesota', 1, 0) AS "state_Minnesota",
     DECODE("state_Mississippi", 'Mississippi', 1, 0) AS "state_Mississippi",
     DECODE("state_Missouri", 'Missouri', 1, 0) AS "state_Missouri",
     DECODE("state_Montana", 'Montana', 1, 0) AS "state_Montana",
     DECODE("state_Nebraska", 'Nebraska', 1, 0) AS "state_Nebraska",
     DECODE("state_Nevada", 'Nevada', 1, 0) AS "state_Nevada",
     DECODE("state_New_Hampshire", 'New Hampshire', 1, 0) AS "state_New_Hampshire",
     DECODE("state_New_Jersey", 'New Jersey', 1, 0) AS "state_New_Jersey",
     DECODE("state_New_Mexico", 'New Mexico', 1, 0) AS "state_New_Mexico",
     DECODE("state_New_York", 'New York', 1, 0) AS "state_New_York",
     DECODE("state_North_Carolina", 'North Carolina', 1, 0) AS "state_North_Carolina",
     DECODE("state_North_Dakota", 'North Dakota', 1, 0) AS "state_North_Dakota",
     DECODE("state_Northern_Mariana_Islands", 'Northern Mariana Islands', 1, 0) AS "state_Northern_Mariana_Islands",
     DECODE("state_Ohio", 'Ohio', 1, 0) AS "state_Ohio",
     DECODE("state_Oklahoma", 'Oklahoma', 1, 0) AS "state_Oklahoma",
     DECODE("state_Oregon", 'Oregon', 1, 0) AS "state_Oregon",
     DECODE("state_Pennsylvania", 'Pennsylvania', 1, 0) AS "state_Pennsylvania",
     DECODE("state_Puerto_Rico", 'Puerto Rico', 1, 0) AS "state_Puerto_Rico",
     DECODE("state_Rhode_Island", 'Rhode Island', 1, 0) AS "state_Rhode_Island",
     DECODE("state_South_Carolina", 'South Carolina', 1, 0) AS "state_South_Carolina",
     DECODE("state_South_Dakota", 'South Dakota', 1, 0) AS "state_South_Dakota",
     DECODE("state_Tennessee", 'Tennessee', 1, 0) AS "state_Tennessee",
     DECODE("state_Texas", 'Texas', 1, 0) AS "state_Texas",
     DECODE("state_Utah", 'Utah', 1, 0) AS "state_Utah",
     DECODE("state_Vermont", 'Vermont', 1, 0) AS "state_Vermont",
     DECODE("state_Virgin_Islands", 'Virgin Islands', 1, 0) AS "state_Virgin_Islands",
     DECODE("state_Virginia", 'Virginia', 1, 0) AS "state_Virginia",
     DECODE("state_Washington", 'Washington', 1, 0) AS "state_Washington",
     DECODE("state_West_Virginia", 'West Virginia', 1, 0) AS "state_West_Virginia",
     DECODE("state_Wisconsin", 'Wisconsin', 1, 0) AS "state_Wisconsin",
     ("date") - (MIN("date") OVER (PARTITION BY "state" )) AS "elapsed_days" 
   FROM
 (
                
   SELECT
     
                    "state",
     "date",
     "deaths",
     "cases",
     "state" AS "state_Alabama",
     "state" AS "state_Alaska",
     "state" AS "state_Arizona",
     "state" AS "state_Arkansas",
     "state" AS "state_California",
     "state" AS "state_Colorado",
     "state" AS "state_Connecticut",
     "state" AS "state_Delaware",
     "state" AS "state_District_of_Columbia",
     "state" AS "state_Florida",
     "state" AS "state_Georgia",
     "state" AS "state_Guam",
     "state" AS "state_Hawaii",
     "state" AS "state_Idaho",
     "state" AS "state_Illinois",
     "state" AS "state_Indiana",
     "state" AS "state_Iowa",
     "state" AS "state_Kansas",
     "state" AS "state_Kentucky",
     "state" AS "state_Louisiana",
     "state" AS "state_Maine",
     "state" AS "state_Maryland",
     "state" AS "state_Massachusetts",
     "state" AS "state_Michigan",
     "state" AS "state_Minnesota",
     "state" AS "state_Mississippi",
     "state" AS "state_Missouri",
     "state" AS "state_Montana",
     "state" AS "state_Nebraska",
     "state" AS "state_Nevada",
     "state" AS "state_New_Hampshire",
     "state" AS "state_New_Jersey",
     "state" AS "state_New_Mexico",
     "state" AS "state_New_York",
     "state" AS "state_North_Carolina",
     "state" AS "state_North_Dakota",
     "state" AS "state_Northern_Mariana_Islands",
     "state" AS "state_Ohio",
     "state" AS "state_Oklahoma",
     "state" AS "state_Oregon",
     "state" AS "state_Pennsylvania",
     "state" AS "state_Puerto_Rico",
     "state" AS "state_Rhode_Island",
     "state" AS "state_South_Carolina",
     "state" AS "state_South_Dakota",
     "state" AS "state_Tennessee",
     "state" AS "state_Texas",
     "state" AS "state_Utah",
     "state" AS "state_Vermont",
     "state" AS "state_Virgin_Islands",
     "state" AS "state_Virginia",
     "state" AS "state_Washington",
     "state" AS "state_West_Virginia",
     "state" AS "state_Wisconsin" 
                
   FROM
 (
   SELECT
     "state",
     "date",
     (SUM("deaths")) AS deaths,
     (SUM("cases")) AS cases 
   FROM
 ( 
   SELECT
     "date",
     "state",
     "cases",
     "deaths" 
   FROM
 "v_temp_schema"."_verticapy_tmp_deaths_v_mldb_29a6b70297bb11efa8720242ac120002_") 
VERTICAPY_SUBTABLE 
   GROUP BY 1,
     2) 
VERTICAPY_SUBTABLE) 
VERTICAPY_SUBTABLE) 
VERTICAPY_SUBTABLE

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

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 = vp.read_csv("deaths.csv").groupby(
    ["date"],
    [
        fun.sum(covid19["deaths"])._as("deaths"),
        fun.sum(covid19["cases"])._as("cases"),
    ],
).search("date > '04-01-2020'")

Machine Learning

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

from verticapy.machine_learning.vertica.tsa import VAR

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

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

Cases:

model.plot(
    covid19,
    start = 37,
    npredictions = 10,
    idx = 0,
)

Deaths:

model.plot(
    covid19,
    start = 37,
    npredictions = 10,
    idx = 1,
)

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!