Capítulo 2 Revisão - Linguagem R

2.1 Data frames

Data frames são a principal classe de objetos do R. São como tabelas de Excel: estruturas compostas por linhas e colunas.

Data frames são criados geralmente usando funções de importar dados, como read.csv2(), mas também podem ser criados explicitamente usando a função data.frame().

Um exemplo de data frame:

library(tidyverse)

head(iris)
##   Sepal.Length Sepal.Width Petal.Length Petal.Width Species
## 1          5.1         3.5          1.4         0.2  setosa
## 2          4.9         3.0          1.4         0.2  setosa
## 3          4.7         3.2          1.3         0.2  setosa
## 4          4.6         3.1          1.5         0.2  setosa
## 5          5.0         3.6          1.4         0.2  setosa
## 6          5.4         3.9          1.7         0.4  setosa
str(iris)
## 'data.frame':    150 obs. of  5 variables:
##  $ Sepal.Length: num  5.1 4.9 4.7 4.6 5 5.4 4.6 5 4.4 4.9 ...
##  $ Sepal.Width : num  3.5 3 3.2 3.1 3.6 3.9 3.4 3.4 2.9 3.1 ...
##  $ Petal.Length: num  1.4 1.4 1.3 1.5 1.4 1.7 1.4 1.5 1.4 1.5 ...
##  $ Petal.Width : num  0.2 0.2 0.2 0.2 0.2 0.4 0.3 0.2 0.2 0.1 ...
##  $ Species     : Factor w/ 3 levels "setosa","versicolor",..: 1 1 1 1 1 1 1 1 1 1 ...

No R, enfatiza-se muito que, para permitir um manuseio mais fácil dos dados, as variáveis sejam armazenadas em colunas e os valores em células. Isso é um princípio de uma filosofia criada por Hadley Wickham chamada tidy data.

2.2 tidyverse

Tidyverse

Tidyverse

O tidyverse (também chamado de hadleyverse) é um conjunto de pacotes R que facilita o manuseio de dados. Atualmente agrega os seguintes pacotes:

  • ggplot2, para visualização de dados;
  • dplyr, para manuseio de dados;
  • tidyr, para arrumação de dados;
  • readr, para importaçao de dados;
  • purrr, para programação funcional;
  • stringr, para manuseio de strings;
  • etc.

Você pode instalar todos os pacotes do tidyverse usando o comando install.packages("tidyverse").

2.3 Datas

Para trabalhar com datas e horários (ou períodos), o pacote lubridate é indispensável. Ele reúne praticamente todas as funções necessárias com essas variáveis usando códigos rápidos e de sintaxe amigável.

Algumas funções do lubridate são especialmente úteis para nós brasileiros, devido ao fato de usarmos o padrão “dd-mm-aaaa” e não o “aaaa-mm-dd”, que é o formato nativo do R.

Suponha que você carregue para o R um data frame desse tipo:

df <- data.frame(data = c("20/01/2017", "01-02-2017", "11122017"),
                 valor = rnorm(3),
                 stringsAsFactors = FALSE)
str(df)
## 'data.frame':    3 obs. of  2 variables:
##  $ data : chr  "20/01/2017" "01-02-2017" "11122017"
##  $ valor: num  0.2375 1.0513 -0.0555

Como você viu no output da função str(), o R converteu a coluna data para caracter por não saber bem o que ela significa. Sem o lubridate, seria trabalhoso converter essa coluna para o formato Date. Veja como isso é fácil com o lubridate:

library(lubridate)

df$data <- dmy(df$data)
str(df)
## 'data.frame':    3 obs. of  2 variables:
##  $ data : Date, format: "2017-01-20" "2017-02-01" ...
##  $ valor: num  0.2375 1.0513 -0.0555

O lubridate consegui com sucesso converter a coluna para Date. Com isso, ela está pronta para executar qualquer operação com datas nativas do R (ou até mesmo para usar como eixo de um gráfico no ggplot2).

Também é possível trabalhar com o formato datetime:

# carregue o pacote magrittr para poder usar os pipes
library(magrittr)
## 
## Attaching package: 'magrittr'
## The following object is masked from 'package:purrr':
## 
##     set_names
## The following object is masked from 'package:tidyr':
## 
##     extract
dmy_hms("01/09/1993 22:14:37")
## [1] "1993-09-01 22:14:37 UTC"
dmy_hms("01/09/1993 22:14:37") %>% class
## [1] "POSIXct" "POSIXt"

Após converter um string para formato Date, é possível extrair seus componentes usando as funções day(), month(), year(), hour(), etc.

today() %>% day()
## [1] 24
today() %>% month()
## [1] 10
now() %>% minute()
## [1] 34

O lubridate é especialmente útil com intervalos. Suponha que você deseja conferir se dois intervalos de tempo se chocam (apresentam algum período em comum):

viagem_sp <- interval(dmy("19/07/2017", tz = "America/Sao_Paulo"),
                      dmy("08/08/2017", tz = "America/Sao_Paulo"))

shows_u2 <- interval(dmy("01/08/2017", tz = "America/Sao_Paulo"),
                      dmy("05/08/2017", tz = "America/Sao_Paulo"))

int_overlaps(viagem_sp, shows_u2)
## [1] TRUE

Também é possível fazer operações matemáticas com datas:

now()
## [1] "2017-10-24 21:34:21 BRST"
now() + dminutes(2)
## [1] "2017-10-24 21:36:21 BRST"
now() + dweeks(1)
## [1] "2017-10-31 21:34:21 BRST"

Uma função que eu acho especialmente útil e a utilizo bastante é a de arredondar datas, ou seja, de descobrir qual o primeiro ou último dia da semana / mês / ano / etc. de uma dada data:

# retornar primeiro e ultimo dia da semana atual
today() %>% floor_date("week")
## [1] "2017-10-22"
today() %>% ceiling_date("week")
## [1] "2017-10-28 22:00:00 BRST"
# Mas atencão! Muito cuidado com a classe do output!
today() %>% floor_date("week") %>% class
## [1] "Date"
today() %>% ceiling_date("week") %>% class
## [1] "POSIXct" "POSIXt"
today() %>% ceiling_date("month") %>% class
## [1] "Date"
# para evitar erros no codigo, certifique-se sempre que o objeto pertence a classe...
#... que ele deveria pertencer
today() %>% ceiling_date("week") %>% as.Date() %>% class
## [1] "Date"

2.4 ggplot2

ggplot2 é o principal pacote de gráficos do R. Seu elevado grau de customização e facilidade de uso o tornaram não só um dos pacotes R mais baixados mas também uma das suítes gráficas mais populares do mundo, fazendo frente a softwares caros como Tableau, Qlikview e Power BI.

É bom enfatizar que o ggplot2 é orientado a data frames e não a objetos do tipo ts. Por exemplo, um uso comum do pacote para gráficos de séries temporais é por meio da função ggplot2::geom_line():

Gráfico de linha

library(ggplot2)
data(economics)
str(economics)
## Classes 'tbl_df', 'tbl' and 'data.frame':    574 obs. of  6 variables:
##  $ date    : Date, format: "1967-07-01" "1967-08-01" ...
##  $ pce     : num  507 510 516 513 518 ...
##  $ pop     : int  198712 198911 199113 199311 199498 199657 199808 199920 200056 200208 ...
##  $ psavert : num  12.5 12.5 11.7 12.5 12.5 12.1 11.7 12.2 11.6 12.2 ...
##  $ uempmed : num  4.5 4.7 4.6 4.9 4.7 4.8 5.1 4.5 4.1 4.6 ...
##  $ unemploy: int  2944 2945 2958 3143 3066 3018 2878 3001 2877 2709 ...
ggplot(data = economics, aes(x = date, y = uempmed)) + 
  geom_line() +
  # curva de tendencia
  geom_smooth(method = "loess", se = FALSE)

Neste gráfico, definimos o data frame economics como argumento de dados, a variável date como eixo horizontal e a variável uempmed (duração média do tempo desempregado) como eixo vertical. Para indicar uma curva de tendência (observe como a curva azil segue o movimento da série), usamos a função geom_smooth().

Gráfico de pontos

Digamos então que gostaríamos de plotar duas variáveis (ex.: taxa de poupança pessoal e despesas pessoais) para analisar a relação entre ambas, considerando também o fator tempo. Isso pode ser feito da seguinte maneira:

ggplot(economics, aes(x = psavert, y = pce, color = date)) + 
  geom_point()

Gráfico de barras

Agora vamos combinar o melhor dos mundos do tidyverse: Suponha que você deseja calcular o desemprego médio anual dos últimos 10 anos e exibir esses dados em um gráfico de barras. Como isso seria feito?

# calcular o desemprego medio anual dos ultimos 10 anos
economics %>% 
  filter(year(date) >= year(today()) - 10) %>% # filtra os ultimos 10 anos
  mutate(taxa_desemprego = 100 * unemploy / pop) %>% # calcula a taxa de desemprego
  group_by(ano = year(date)) %>%  # agrupa os dados por ano
  summarise(taxa_desemprego_media = mean(taxa_desemprego)) %>% # calcula a taxa de desemprego media por ano 
  ggplot(aes(x = ano, y = taxa_desemprego_media)) +
    geom_col() +
    geom_label(aes(label = round(taxa_desemprego_media, 2))) +
    theme_bw() +
    labs(x = NULL, y = "Taxa de desemprego média (%)",
         title = "Variação da taxa de desemprego médio anual",
         subtitle = "Desde 2010 o indicador está em tendência de queda",
         caption = "Gráfico feito com ggplot2")

Histograma

Suponha que se deseja analisar a distribuição da variação da população mensal e anual. Um histograma é uma excelente ferramenta gráfica para esse objetivo:

# calcular a distribuicao do crescimento populacional mensal
economics %>% 
  mutate(variacao_populacional = (pop / lag(pop, 1)) - 1) %>% 
  ggplot(aes(x = variacao_populacional)) + # um histograma precisa apenas da variavel para o eixo x
    geom_histogram()

O histograma nos ajuda a identificar anomalias, como o período onde a população decresceu de um mês para o outro. Para saber quando isso aconteceu, usamos o código abaixo:

economics %>% 
  mutate(variacao_populacional = (pop / lag(pop, 1)) - 1) %>% 
  filter(variacao_populacional < 0)
## # A tibble: 1 x 7
##         date     pce    pop psavert uempmed unemploy variacao_populacional
##       <date>   <dbl>  <int>   <dbl>   <dbl>    <int>                 <dbl>
## 1 2010-04-01 10106.9 309191     5.6    22.1    15325         -6.791457e-05

Boxplot

Agora o desafio é estudar a distribuição da variável da taxa de poupança pessoal agrupada por mês do ano. Em casos onde se deseja analisar a distribuição de uma mesma variável em diferentes grupos, o boxplot é uma boa pedida:

economics %>% 
  mutate(mes = month(date)) %>%  # criar coluna de mes
  ggplot(aes(x = as.character(mes), y = psavert)) + 
    geom_boxplot()

Veja que tivemos que forçar a variável mês a ser um objeto do tipo character para que o ggplot2 entendesse que se tratam de grupos de dados distintos.

2.5 Séries temporais no R

Na verdade, todo o tidyverse é voltado para objetos do tipo data frame, com exceção do purrr, que foca em listas. Grande parte do universo de séries temporais é feita usando objetos do tipo ts. As funções de modelagem dos pacotes forecast e mafs, por exemplo, aceitam como inputs apenas objetos da classe ts.

Portanto, nem sempre o conhecimento em tidyverse resolverá todos os problemas em programação R.

Um objeto do tipo ts pode ser criado da seguinte maneira:

minha.st <- ts(rnorm(200), start = c(1991, 1), frequency = 12)
# o tidyverse não oferece suporte nativo a objetos ts.
# contudo, o pacote forecast consegue facilitar o plot de STs em graficos do ggplot2:
library(forecast)
autoplot(minha.st)

2.6 Gráficos interativos com dygraphs

Acha os gráficos do ggplot2 chatos e sem vida? Com o pacote dygraphs é possível criar gráficos com recursos interativos:

library(dygraphs)
dygraph(AirPassengers)

2.7 Referências: