How severe weather events are harmful to population health

Leandro Guerra - @leandro_war

www.artedosdados.com.br

Resumo - O objetivo deste relatório é apresentar a biblioteca pandas como ferramenta para análise de dados. Será reproduzido o estudo disponível em http://rpubs.com/leandro_guerra/Storm_Database_Study, que foi inicialmente construído em R. O objetivo não é comparar as duas linguagens, mas sim introduzir o conceito de dataframes dentro do Python. Também não pensamos em otimização de código, visto que os conceitos básicos devem ser entendidos antes de pensar em uma solução mais efetiva.

Processamento dos Dados


In [1]:
#Importando as bibliotecas necessárias para análise
import pandas as pd
import io
import urllib2
import bz2

In [2]:
#Abrindo a URL e descompactando o arquivo .bz2 
url = "https://d396qusza40orc.cloudfront.net/repdata%2Fdata%2FStormData.csv.bz2"
raw_bz2 = urllib2.urlopen(url).read()
data = bz2.decompress(raw_bz2)
df = pd.read_csv(io.BytesIO(data))
df.head()


Out[2]:
<class 'pandas.core.frame.DataFrame'>
Int64Index: 5 entries, 0 to 4
Data columns (total 37 columns):
STATE__       5  non-null values
BGN_DATE      5  non-null values
BGN_TIME      5  non-null values
TIME_ZONE     5  non-null values
COUNTY        5  non-null values
COUNTYNAME    5  non-null values
STATE         5  non-null values
EVTYPE        5  non-null values
BGN_RANGE     5  non-null values
BGN_AZI       0  non-null values
BGN_LOCATI    0  non-null values
END_DATE      0  non-null values
END_TIME      0  non-null values
COUNTY_END    5  non-null values
COUNTYENDN    0  non-null values
END_RANGE     5  non-null values
END_AZI       0  non-null values
END_LOCATI    0  non-null values
LENGTH        5  non-null values
WIDTH         5  non-null values
F             5  non-null values
MAG           5  non-null values
FATALITIES    5  non-null values
INJURIES      5  non-null values
PROPDMG       5  non-null values
PROPDMGEXP    5  non-null values
CROPDMG       5  non-null values
CROPDMGEXP    0  non-null values
WFO           0  non-null values
STATEOFFIC    0  non-null values
ZONENAMES     0  non-null values
LATITUDE      5  non-null values
LONGITUDE     5  non-null values
LATITUDE_E    5  non-null values
LONGITUDE_    5  non-null values
REMARKS       0  non-null values
REFNUM        5  non-null values
dtypes: float64(19), object(18)

In [3]:
#Selecionando apenas os atributos mais relevantes

In [4]:
subSet = df[['BGN_DATE','PROPDMG','CROPDMG','EVTYPE','INJURIES','FATALITIES']]

In [5]:
subSet


Out[5]:
<class 'pandas.core.frame.DataFrame'>
Int64Index: 902297 entries, 0 to 902296
Data columns (total 6 columns):
BGN_DATE      902297  non-null values
PROPDMG       902297  non-null values
CROPDMG       902297  non-null values
EVTYPE        902297  non-null values
INJURIES      902297  non-null values
FATALITIES    902297  non-null values
dtypes: float64(4), object(2)

In [6]:
#Verificando o dataframe

In [7]:
subSet.head()


Out[7]:
BGN_DATE PROPDMG CROPDMG EVTYPE INJURIES FATALITIES
0 4/18/1950 0:00:00 25.0 0 TORNADO 15 0
1 4/18/1950 0:00:00 2.5 0 TORNADO 0 0
2 2/20/1951 0:00:00 25.0 0 TORNADO 2 0
3 6/8/1951 0:00:00 2.5 0 TORNADO 2 0
4 11/15/1951 0:00:00 2.5 0 TORNADO 2 0

In [8]:
#Inserindo nova variável

In [9]:
subSet['ECONOMICDMG'] = subSet['PROPDMG'] + subSet['CROPDMG']

In [10]:
subSet.head()


Out[10]:
BGN_DATE PROPDMG CROPDMG EVTYPE INJURIES FATALITIES ECONOMICDMG
0 4/18/1950 0:00:00 25.0 0 TORNADO 15 0 25.0
1 4/18/1950 0:00:00 2.5 0 TORNADO 0 0 2.5
2 2/20/1951 0:00:00 25.0 0 TORNADO 2 0 25.0
3 6/8/1951 0:00:00 2.5 0 TORNADO 2 0 2.5
4 11/15/1951 0:00:00 2.5 0 TORNADO 2 0 2.5

In [11]:
#Vamos criar outro dataframe, agregando as informações por ano

In [12]:
import datetime
#Vamos manipular datas e converter BGN_DATE do formato string para o formato datetime

In [13]:
subSet['BGN_DATE'] = pd.to_datetime(subSet['BGN_DATE'])

In [14]:
subSet.head(5)


Out[14]:
BGN_DATE PROPDMG CROPDMG EVTYPE INJURIES FATALITIES ECONOMICDMG
0 1950-04-18 00:00:00 25.0 0 TORNADO 15 0 25.0
1 1950-04-18 00:00:00 2.5 0 TORNADO 0 0 2.5
2 1951-02-20 00:00:00 25.0 0 TORNADO 2 0 25.0
3 1951-06-08 00:00:00 2.5 0 TORNADO 2 0 2.5
4 1951-11-15 00:00:00 2.5 0 TORNADO 2 0 2.5

In [15]:
#Agrupamento das data por ano

In [16]:
subSet['BGN_DATE'] = subSet.BGN_DATE.apply(datetime.date.strftime, args=('%Y',))

In [17]:
subSet.head(5)


Out[17]:
BGN_DATE PROPDMG CROPDMG EVTYPE INJURIES FATALITIES ECONOMICDMG
0 1950 25.0 0 TORNADO 15 0 25.0
1 1950 2.5 0 TORNADO 0 0 2.5
2 1951 25.0 0 TORNADO 2 0 25.0
3 1951 2.5 0 TORNADO 2 0 2.5
4 1951 2.5 0 TORNADO 2 0 2.5

Importamos agora a biblioteca numpy para os cálculos de média, soma e desvio padrão


In [18]:
import numpy as np

Agrupamos os dados em uma variável auxiliar (para preservar o dataframe original) - Dados agrupados por ano e tipo de evento


In [19]:
aux =subSet[['BGN_DATE','EVTYPE','INJURIES','FATALITIES','ECONOMICDMG']].groupby(['BGN_DATE','EVTYPE'])

Seleção dos atributos utilizados para análise com os repectivos valores de média, desvio e soma


In [20]:
aux = aux[['INJURIES','FATALITIES','ECONOMICDMG']].agg([np.mean, np.std, np.sum])

Exemplo da estrutura agregada


In [21]:
aux['FATALITIES']['sum']


Out[21]:
BGN_DATE  EVTYPE   
1950      TORNADO       70
1951      TORNADO       34
1952      TORNADO      230
1953      TORNADO      519
1954      TORNADO       36
1955      HAIL           0
          TORNADO      129
          TSTM WIND      0
1956      HAIL           0
          TORNADO       83
          TSTM WIND      0
1957      HAIL           0
          TORNADO      193
          TSTM WIND      0
1958      HAIL           0
...
2011      MARINE STRONG WIND            2
          MARINE THUNDERSTORM WIND      3
          RIP CURRENT                  29
          SEICHE                        0
          SLEET                         0
          STORM SURGE/TIDE              0
          STRONG WIND                  10
          THUNDERSTORM WIND            54
          TORNADO                     587
          TROPICAL STORM                4
          TSUNAMI                       1
          WATERSPOUT                    0
          WILDFIRE                      6
          WINTER STORM                  1
          WINTER WEATHER                2
Name: sum, Length: 2326, dtype: float64

Agora, agregamos os novos dados à variável eventYear e fazemos a concatenação de cada atributo Renomeamos a coluna 'sum' para o respectivo nome da ocorrência


In [22]:
eventYear  = pd.DataFrame(aux['FATALITIES']['sum']).rename(columns={'sum': 'FATALITIES'}, inplace=False)

In [23]:
eventYear['INJURIES'] = aux['INJURIES']['sum']

In [24]:
eventYear['ECONOMICDMG'] = aux['ECONOMICDMG']['sum']

Dados agregados por ano e tipo de evento, associados a cada ocorrência.


In [25]:
eventYear.head()


Out[25]:
FATALITIES INJURIES ECONOMICDMG
BGN_DATE EVTYPE
1950 TORNADO 70 659 16999.15
1951 TORNADO 34 524 10560.99
1952 TORNADO 230 1915 16679.74
1953 TORNADO 519 5131 19182.20
1954 TORNADO 36 715 23367.82

In [26]:
type(eventYear)


Out[26]:
pandas.core.frame.DataFrame

In [27]:
for cada in eventYear:
    print cada


FATALITIES
INJURIES
ECONOMICDMG

In [28]:
eventYear[['FATALITIES']].sum()


Out[28]:
FATALITIES    15145
dtype: float64

In [28]: