Modelos Estatísticos - BICT/MAR - UNIFESP

Aula 2 - Análise exploratória de dados - Parte I

Introdução

Trabalharemos nesta aula com a base de dados storms disponível no pacote do R dplyr.Este banco de dados é um dos vários conjuntos de dados disponíveis no National Hurricane Center (NHC) Data Archive, que faz parte da National Oceanic and Atmospheric Administration (NOAA).

Pacotes necessários

Utilizaremos os pacotes dplyr e ggplot2


# instalando os pacotes
# install.packages(c("dplyr", "ggplot2"))
# carrega os pacotes
library(dplyr)
## 
## Attaching package: 'dplyr'
## The following objects are masked from 'package:stats':
## 
##     filter, lag
## The following objects are masked from 'package:base':
## 
##     intersect, setdiff, setequal, union
library(ggplot2)

Dados de furacão do Atlântico

# visualiza a base de dados
storms
## # A tibble: 19,066 x 13
##    name   year month   day  hour   lat  long status        categ~1  wind press~2
##    <chr> <dbl> <dbl> <int> <dbl> <dbl> <dbl> <fct>           <dbl> <int>   <int>
##  1 Amy    1975     6    27     0  27.5 -79   tropical dep~      NA    25    1013
##  2 Amy    1975     6    27     6  28.5 -79   tropical dep~      NA    25    1013
##  3 Amy    1975     6    27    12  29.5 -79   tropical dep~      NA    25    1013
##  4 Amy    1975     6    27    18  30.5 -79   tropical dep~      NA    25    1013
##  5 Amy    1975     6    28     0  31.5 -78.8 tropical dep~      NA    25    1012
##  6 Amy    1975     6    28     6  32.4 -78.7 tropical dep~      NA    25    1012
##  7 Amy    1975     6    28    12  33.3 -78   tropical dep~      NA    25    1011
##  8 Amy    1975     6    28    18  34   -77   tropical dep~      NA    30    1006
##  9 Amy    1975     6    29     0  34.4 -75.8 tropical sto~      NA    35    1004
## 10 Amy    1975     6    29     6  34   -74.8 tropical sto~      NA    40    1002
## # ... with 19,056 more rows, 2 more variables:
## #   tropicalstorm_force_diameter <int>, hurricane_force_diameter <int>, and
## #   abbreviated variable names 1: category, 2: pressure

Você pode encontrar algumas descrições técnicas de tempestades dando uma olhada em seu manual (ou documentação de ajuda): ?storms.

Storms é um objeto tibble com dados em formato tabular.

A forma como os tibbles são impressos é muito interessante. O número de linhas exibidas é limitado a 10; também, dependendo da largura do espaço de impressão, você verá apenas algumas colunas mostradas para caber nessa largura. Observe que abaixo do nome de cada coluna há uma abreviação de três letras entre colchetes angulares, essa abreviação indica o tipo de dado usado pelo R para armazenar os valores. Por exemplo, o nome da primeira coluna tem o tipo que representa dados de caracteres, o year da segunda coluna é do tipo ou double, ou seja, números reais ou números com dígitos decimais. A quarta coluna day é do tipo ou integer (números sem casas decimais).

Aqui está uma descrição completa de todas as colunas:

name: Nome da Tempestade

year, month e day: Data do relatório

hour: Hora do relatório (em UTC)

lat: Latitude

long: Longitude

status: Classificação de tempestade (Depressão Tropical, Tempestade Tropical ou Furacão)

category: categoria de tempestade Saffir-Simpson (estimada a partir da velocidade do vento. -1 = Depressão Tropical, 0 = Tempestade Tropical)

wind: velocidade máxima sustentada do vento da tempestade (em nós)

pressure: pressão do ar no centro da tempestade (em milibares)

tropicalstorm_force_diameter: Diâmetro da área com ventos fortes de tempestade tropical (34 nós ou acima)

hurricane_force_diameter: Diâmetro da área com ventos fortes de furacão (64 nós ou acima)

Analise exploratória

Funções pull() e select()

Nossa primeira pergunta é: qual a cobertura temporal (período em anos) do banco de dados?

Para responder a essa pergunta, precisamos trabalhar com anos de coluna. Existem várias maneiras em R de manipular uma coluna de um objeto tabular. Usando “dplyr”, existem dois tipos básicos de funções para extrair variáveis: pull() e select().

Podemos usar a função pull() que puxa ou extrai uma coluna inteira. Como existem 10.010 elementos em anos, vamos também usar unique() para descobrir o conjunto de valores únicos de ano nos dados. Primeiro, extraímos o ano e depois identificamos ocorrências únicas:

# visualiza a base de dados
unique(pull(storms, year))
##  [1] 1975 1976 1977 1978 1979 1980 1981 1982 1983 1984 1985 1986 1987 1988 1989
## [16] 1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004
## [31] 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019
## [46] 2020 2021

A mesma operação pode ser realizada com select(). A diferença entre pull() e select() está na maneira como a saída é tratada. A função select() retorna a saída em um formato de tabela, enquanto pull() retorna a saída como um vetor R:

unique(select(storms, year))
## # A tibble: 47 x 1
##     year
##    <dbl>
##  1  1975
##  2  1976
##  3  1977
##  4  1978
##  5  1979
##  6  1980
##  7  1981
##  8  1982
##  9  1983
## 10  1984
## # ... with 37 more rows

Que tal aplicar os mesmos comandos para a variável month e day


unique(pull(storms, month))
##  [1]  6  7  8  9 10 11  5 12  4  1

# Nesse caso, seria melhor se os classificássemos:

sort(unique(pull(storms, month)))
##  [1]  1  4  5  6  7  8  9 10 11 12

# para os dias
sort(unique(pull(storms, day)))
##  [1]  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
## [26] 26 27 28 29 30 31

Função filter()

Vamos nos concentrar nas tempestades registradas em 1975. Como as selecionamos? Computacionalmente, esta operação inclui uma condição lógica: year == 1975. Esta condição significa que, de todos os valores de ano disponíveis, obtemos aqueles que correspondem a 1975. Isso é feito através da função “dplyr” filter()


storms75 <- filter(storms, year == 1975)
storms75
## # A tibble: 238 x 13
##    name   year month   day  hour   lat  long status        categ~1  wind press~2
##    <chr> <dbl> <dbl> <int> <dbl> <dbl> <dbl> <fct>           <dbl> <int>   <int>
##  1 Amy    1975     6    27     0  27.5 -79   tropical dep~      NA    25    1013
##  2 Amy    1975     6    27     6  28.5 -79   tropical dep~      NA    25    1013
##  3 Amy    1975     6    27    12  29.5 -79   tropical dep~      NA    25    1013
##  4 Amy    1975     6    27    18  30.5 -79   tropical dep~      NA    25    1013
##  5 Amy    1975     6    28     0  31.5 -78.8 tropical dep~      NA    25    1012
##  6 Amy    1975     6    28     6  32.4 -78.7 tropical dep~      NA    25    1012
##  7 Amy    1975     6    28    12  33.3 -78   tropical dep~      NA    25    1011
##  8 Amy    1975     6    28    18  34   -77   tropical dep~      NA    30    1006
##  9 Amy    1975     6    29     0  34.4 -75.8 tropical sto~      NA    35    1004
## 10 Amy    1975     6    29     6  34   -74.8 tropical sto~      NA    40    1002
## # ... with 228 more rows, 2 more variables: tropicalstorm_force_diameter <int>,
## #   hurricane_force_diameter <int>, and abbreviated variable names 1: category,
## #   2: pressure

Algumas análises possíveis a partir dos dados de 1975. Por exemplo o uso da função distinct() para saber os nomes dos furacões em 1975.


unique(pull(storms75, name))
## [1] "Amy"      "Blanche"  "Caroline" "Doris"    "Eloise"   "Faye"     "Gladys"  
## [8] "Hallie"
distinct(storms75, name)
## # A tibble: 8 x 1
##   name    
##   <chr>   
## 1 Amy     
## 2 Blanche 
## 3 Caroline
## 4 Doris   
## 5 Eloise  
## 6 Faye    
## 7 Gladys  
## 8 Hallie

Podemos contar o número de linhas ou registros para cada evento e obter as frequencias absolutas (n).


count(storms75, name)
## # A tibble: 8 x 2
##   name         n
##   <chr>    <int>
## 1 Amy         31
## 2 Blanche     20
## 3 Caroline    33
## 4 Doris       29
## 5 Eloise      46
## 6 Faye        19
## 7 Gladys      46
## 8 Hallie      14

Mais alguns usos da função filter()


# registros entre 1975 e 1976

storms75and76 <- filter(storms, year == 1975 | year == 1976)
storms75and76
## # A tibble: 364 x 13
##    name   year month   day  hour   lat  long status        categ~1  wind press~2
##    <chr> <dbl> <dbl> <int> <dbl> <dbl> <dbl> <fct>           <dbl> <int>   <int>
##  1 Amy    1975     6    27     0  27.5 -79   tropical dep~      NA    25    1013
##  2 Amy    1975     6    27     6  28.5 -79   tropical dep~      NA    25    1013
##  3 Amy    1975     6    27    12  29.5 -79   tropical dep~      NA    25    1013
##  4 Amy    1975     6    27    18  30.5 -79   tropical dep~      NA    25    1013
##  5 Amy    1975     6    28     0  31.5 -78.8 tropical dep~      NA    25    1012
##  6 Amy    1975     6    28     6  32.4 -78.7 tropical dep~      NA    25    1012
##  7 Amy    1975     6    28    12  33.3 -78   tropical dep~      NA    25    1011
##  8 Amy    1975     6    28    18  34   -77   tropical dep~      NA    30    1006
##  9 Amy    1975     6    29     0  34.4 -75.8 tropical sto~      NA    35    1004
## 10 Amy    1975     6    29     6  34   -74.8 tropical sto~      NA    40    1002
## # ... with 354 more rows, 2 more variables: tropicalstorm_force_diameter <int>,
## #   hurricane_force_diameter <int>, and abbreviated variable names 1: category,
## #   2: pressure

# outra forma

filter(storms, year %in% c(1975, 1976))
## # A tibble: 364 x 13
##    name   year month   day  hour   lat  long status        categ~1  wind press~2
##    <chr> <dbl> <dbl> <int> <dbl> <dbl> <dbl> <fct>           <dbl> <int>   <int>
##  1 Amy    1975     6    27     0  27.5 -79   tropical dep~      NA    25    1013
##  2 Amy    1975     6    27     6  28.5 -79   tropical dep~      NA    25    1013
##  3 Amy    1975     6    27    12  29.5 -79   tropical dep~      NA    25    1013
##  4 Amy    1975     6    27    18  30.5 -79   tropical dep~      NA    25    1013
##  5 Amy    1975     6    28     0  31.5 -78.8 tropical dep~      NA    25    1012
##  6 Amy    1975     6    28     6  32.4 -78.7 tropical dep~      NA    25    1012
##  7 Amy    1975     6    28    12  33.3 -78   tropical dep~      NA    25    1011
##  8 Amy    1975     6    28    18  34   -77   tropical dep~      NA    30    1006
##  9 Amy    1975     6    29     0  34.4 -75.8 tropical sto~      NA    35    1004
## 10 Amy    1975     6    29     6  34   -74.8 tropical sto~      NA    40    1002
## # ... with 354 more rows, 2 more variables: tropicalstorm_force_diameter <int>,
## #   hurricane_force_diameter <int>, and abbreviated variable names 1: category,
## #   2: pressure

# outra forma

filter(storms, year %in% 1975:1976)
## # A tibble: 364 x 13
##    name   year month   day  hour   lat  long status        categ~1  wind press~2
##    <chr> <dbl> <dbl> <int> <dbl> <dbl> <dbl> <fct>           <dbl> <int>   <int>
##  1 Amy    1975     6    27     0  27.5 -79   tropical dep~      NA    25    1013
##  2 Amy    1975     6    27     6  28.5 -79   tropical dep~      NA    25    1013
##  3 Amy    1975     6    27    12  29.5 -79   tropical dep~      NA    25    1013
##  4 Amy    1975     6    27    18  30.5 -79   tropical dep~      NA    25    1013
##  5 Amy    1975     6    28     0  31.5 -78.8 tropical dep~      NA    25    1012
##  6 Amy    1975     6    28     6  32.4 -78.7 tropical dep~      NA    25    1012
##  7 Amy    1975     6    28    12  33.3 -78   tropical dep~      NA    25    1011
##  8 Amy    1975     6    28    18  34   -77   tropical dep~      NA    30    1006
##  9 Amy    1975     6    29     0  34.4 -75.8 tropical sto~      NA    35    1004
## 10 Amy    1975     6    29     6  34   -74.8 tropical sto~      NA    40    1002
## # ... with 354 more rows, 2 more variables: tropicalstorm_force_diameter <int>,
## #   hurricane_force_diameter <int>, and abbreviated variable names 1: category,
## #   2: pressure

# outra forma

filter(storms, year < 1976)
## # A tibble: 238 x 13
##    name   year month   day  hour   lat  long status        categ~1  wind press~2
##    <chr> <dbl> <dbl> <int> <dbl> <dbl> <dbl> <fct>           <dbl> <int>   <int>
##  1 Amy    1975     6    27     0  27.5 -79   tropical dep~      NA    25    1013
##  2 Amy    1975     6    27     6  28.5 -79   tropical dep~      NA    25    1013
##  3 Amy    1975     6    27    12  29.5 -79   tropical dep~      NA    25    1013
##  4 Amy    1975     6    27    18  30.5 -79   tropical dep~      NA    25    1013
##  5 Amy    1975     6    28     0  31.5 -78.8 tropical dep~      NA    25    1012
##  6 Amy    1975     6    28     6  32.4 -78.7 tropical dep~      NA    25    1012
##  7 Amy    1975     6    28    12  33.3 -78   tropical dep~      NA    25    1011
##  8 Amy    1975     6    28    18  34   -77   tropical dep~      NA    30    1006
##  9 Amy    1975     6    29     0  34.4 -75.8 tropical sto~      NA    35    1004
## 10 Amy    1975     6    29     6  34   -74.8 tropical sto~      NA    40    1002
## # ... with 228 more rows, 2 more variables: tropicalstorm_force_diameter <int>,
## #   hurricane_force_diameter <int>, and abbreviated variable names 1: category,
## #   2: pressure

Usar uma condição considerando dois fatores (nome e ano)

filter(storms, year == 1975 & name == "Caroline")
## # A tibble: 33 x 13
##    name      year month   day  hour   lat  long status     categ~1  wind press~2
##    <chr>    <dbl> <dbl> <int> <dbl> <dbl> <dbl> <fct>        <dbl> <int>   <int>
##  1 Caroline  1975     8    24    12  22.4 -69.8 tropical ~      NA    25    1011
##  2 Caroline  1975     8    24    18  21.9 -71.1 tropical ~      NA    25    1011
##  3 Caroline  1975     8    25     0  21.6 -72.5 tropical ~      NA    25    1010
##  4 Caroline  1975     8    25     6  21.2 -73.8 tropical ~      NA    25    1010
##  5 Caroline  1975     8    25    12  20.9 -75.1 tropical ~      NA    25    1011
##  6 Caroline  1975     8    25    18  20.6 -76.4 tropical ~      NA    25    1011
##  7 Caroline  1975     8    26     0  20.4 -77.7 tropical ~      NA    25    1011
##  8 Caroline  1975     8    26     6  20.3 -79   tropical ~      NA    25    1011
##  9 Caroline  1975     8    26    12  20.2 -80.3 tropical ~      NA    25    1012
## 10 Caroline  1975     8    26    18  20.2 -81.6 tropical ~      NA    25    1012
## # ... with 23 more rows, 2 more variables: tropicalstorm_force_diameter <int>,
## #   hurricane_force_diameter <int>, and abbreviated variable names 1: category,
## #   2: pressure

filter(storms, name == "Caroline" & year == 1975)
## # A tibble: 33 x 13
##    name      year month   day  hour   lat  long status     categ~1  wind press~2
##    <chr>    <dbl> <dbl> <int> <dbl> <dbl> <dbl> <fct>        <dbl> <int>   <int>
##  1 Caroline  1975     8    24    12  22.4 -69.8 tropical ~      NA    25    1011
##  2 Caroline  1975     8    24    18  21.9 -71.1 tropical ~      NA    25    1011
##  3 Caroline  1975     8    25     0  21.6 -72.5 tropical ~      NA    25    1010
##  4 Caroline  1975     8    25     6  21.2 -73.8 tropical ~      NA    25    1010
##  5 Caroline  1975     8    25    12  20.9 -75.1 tropical ~      NA    25    1011
##  6 Caroline  1975     8    25    18  20.6 -76.4 tropical ~      NA    25    1011
##  7 Caroline  1975     8    26     0  20.4 -77.7 tropical ~      NA    25    1011
##  8 Caroline  1975     8    26     6  20.3 -79   tropical ~      NA    25    1011
##  9 Caroline  1975     8    26    12  20.2 -80.3 tropical ~      NA    25    1012
## 10 Caroline  1975     8    26    18  20.2 -81.6 tropical ~      NA    25    1012
## # ... with 23 more rows, 2 more variables: tropicalstorm_force_diameter <int>,
## #   hurricane_force_diameter <int>, and abbreviated variable names 1: category,
## #   2: pressure

Operações de agrupamento (group_by())

Outra tarefa comum ao explorar dados tem a ver com cálculos aplicados a determinados grupos ou categorias de dados. “dplyr” fornece a função group_by() que recebe uma tabela de dados e especificamos a(s) coluna(s) nas quais as linhas serão agrupadas. Na maioria das vezes, você usará group_by() com a função summarise(), que como seu nome indica, permite que você calcule um determinado resumo nas colunas especificadas.


# calcular médias dos ventos e pressão para cada furacão

summarise(
  group_by(storms75, name),
  avg_wind = mean(wind),
  avg_pressure = mean(pressure)
)
## # A tibble: 8 x 3
##   name     avg_wind avg_pressure
##   <chr>       <dbl>        <dbl>
## 1 Amy          46.5         995.
## 2 Blanche      45           999.
## 3 Caroline     38.9        1002.
## 4 Doris        67.1         988.
## 5 Eloise       45           999.
## 6 Faye         68.4         988.
## 7 Gladys       66.3         986.
## 8 Hallie       34.6        1005.


# outra forma

avg_wind_pressure_75 <- summarise(
  group_by(storms75, name),
  avg_wind = mean(wind),
  avg_pressure = mean(pressure)
)

avg_wind_pressure_75
## # A tibble: 8 x 3
##   name     avg_wind avg_pressure
##   <chr>       <dbl>        <dbl>
## 1 Amy          46.5         995.
## 2 Blanche      45           999.
## 3 Caroline     38.9        1002.
## 4 Doris        67.1         988.
## 5 Eloise       45           999.
## 6 Faye         68.4         988.
## 7 Gladys       66.3         986.
## 8 Hallie       34.6        1005.

Organizar operações (arrange())

Além das operações group_by(), outro tipo comum de manipulação é a organização de linhas com base nos valores de uma ou mais colunas. Em “dplyr”, isso pode ser facilmente obtido com a função arrange(). A maneira como essa função funciona é passando o nome da tabela e, em seguida, especificando uma ou mais colunas para ordenar as linhas com base em tais valores.


arrange(avg_wind_pressure_75, avg_wind)
## # A tibble: 8 x 3
##   name     avg_wind avg_pressure
##   <chr>       <dbl>        <dbl>
## 1 Hallie       34.6        1005.
## 2 Caroline     38.9        1002.
## 3 Blanche      45           999.
## 4 Eloise       45           999.
## 5 Amy          46.5         995.
## 6 Gladys       66.3         986.
## 7 Doris        67.1         988.
## 8 Faye         68.4         988.

arrange(avg_wind_pressure_75, avg_pressure)
## # A tibble: 8 x 3
##   name     avg_wind avg_pressure
##   <chr>       <dbl>        <dbl>
## 1 Gladys       66.3         986.
## 2 Faye         68.4         988.
## 3 Doris        67.1         988.
## 4 Amy          46.5         995.
## 5 Eloise       45           999.
## 6 Blanche      45           999.
## 7 Caroline     38.9        1002.
## 8 Hallie       34.6        1005.

arrange(avg_wind_pressure_75, desc(avg_wind))
## # A tibble: 8 x 3
##   name     avg_wind avg_pressure
##   <chr>       <dbl>        <dbl>
## 1 Faye         68.4         988.
## 2 Doris        67.1         988.
## 3 Gladys       66.3         986.
## 4 Amy          46.5         995.
## 5 Blanche      45           999.
## 6 Eloise       45           999.
## 7 Caroline     38.9        1002.
## 8 Hallie       34.6        1005.