6 Transformação de dados
A transformação de dados é uma tarefa usualmente dolorosa e demorada, podendo tomar a maior parte do tempo da análise. No entanto, como nosso interesse geralmente é na modelagem dos dados, essa tarefa é muitas vezes negligenciada.
“(…) The fact that data science exists as a field is a colossal failure of statistics. To me, [what I do] is what statistics is all about. It is gaining insight from data using modelling and visualization. Data munging and manipulation is hard and statistics has just said that’s not our domain.”
Hadley Wickham
6.1 Pacotes dplyr
e tidyr
O dplyr
é um dos pacotes mais úteis para realizar manipulação de dados, e procura aliar simplicidade e eficiência de uma forma bastante elegante. Os scripts em R
que fazem uso inteligente dos verbos dplyr
e as facilidades do operador pipe tendem a ficar mais legíveis e organizados, sem perder velocidade de execução.
Por ser um pacote que se propõe a realizar um dos trabalhos mais árduos da análise estatística, e por atingir esse objetivo de forma elegante, eficaz e eficiente, o dplyr
pode ser considerado como uma revolução no R
.
6.1.1 Trabalhando com tibble
s
A tibble
nada mais é do que um data.frame
, mas com um método de impressão mais adequado. Outras diferenças podem ser estudadas neste link.
Vamos assumir que temos a seguinte base de dados:
d_cjsg
## # A tibble: 184,250 × 14
## arq id cd_acordao
## <chr> <chr> <chr>
## 1 /home/storage/abj/raw/TJSP/cjsg/cjsg_mes01/00001.html 1 9381267
## 2 /home/storage/abj/raw/TJSP/cjsg/cjsg_mes01/00001.html 2 8671548
## 3 /home/storage/abj/raw/TJSP/cjsg/cjsg_mes01/00001.html 3 8634338
## 4 /home/storage/abj/raw/TJSP/cjsg/cjsg_mes01/00001.html 4 8536605
## 5 /home/storage/abj/raw/TJSP/cjsg/cjsg_mes01/00001.html 5 8509346
## 6 /home/storage/abj/raw/TJSP/cjsg/cjsg_mes01/00001.html 6 8490681
## 7 /home/storage/abj/raw/TJSP/cjsg/cjsg_mes01/00001.html 7 8466583
## 8 /home/storage/abj/raw/TJSP/cjsg/cjsg_mes01/00001.html 8 8449087
## 9 /home/storage/abj/raw/TJSP/cjsg/cjsg_mes01/00001.html 9 8429536
## 10 /home/storage/abj/raw/TJSP/cjsg/cjsg_mes01/00001.html 10 8331899
## # ... with 184,240 more rows, and 11 more variables: n_processo <chr>,
## # comarca <chr>, data_julgamento <chr>, data_registro <chr>,
## # ementa <chr>, orgao_julgador <chr>, outros_numeros <chr>,
## # relatora <chr>, classe_assunto <chr>, txt_ementa <chr>, result <chr>
6.1.2 As cinco funções principais do dplyr
filter
mutate
select
arrange
summarise
6.1.3 Características
- O input é sempre uma
tibble
, e o output é sempre umtibble
. - No primeiro argumento colocamos o
tibble
, e nos outros argumentos colocamo o que queremos fazer. - A utilização é facilitada com o emprego do operador
%>%
6.1.4 Vantagens
- Utiliza
C
eC++
por trás da maioria das funções, o que geralmente torna o código mais eficiente. - Pode trabalhar com diferentes fontes de dados, como bases relacionais (SQL) e
data.table
.
6.1.5 select
- Utilizar
starts_with(x)
,contains(x)
,matches(x)
,one_of(x)
, etc. - Possível colocar nomes, índices, e intervalos de variáveis com
:
.
d_cjsg %>%
select(id, cd_acordao, comarca, relator = relatora)
## # A tibble: 184,250 × 4
## id cd_acordao comarca relator
## <chr> <chr> <chr> <chr>
## 1 1 9381267 São Paulo Encinas Manfré
## 2 2 8671548 Guarulhos Edison Brandão
## 3 3 8634338 Osasco Ivan Sartori
## 4 4 8536605 Adamantina Walter da Silva
## 5 5 8509346 Limeira Guilherme de Souza Nucci
## 6 6 8490681 São Paulo Roberto Solimene
## 7 7 8466583 Suzano Poças Leitão
## 8 8 8449087 Presidente Prudente Ivan Sartori
## 9 9 8429536 São Paulo Willian Campos
## 10 10 8331899 São Paulo Luis Soares de Mello
## # ... with 184,240 more rows
d_cjsg %>%
select(cd_acordao:comarca, classe_assunto)
## # A tibble: 184,250 × 4
## cd_acordao n_processo comarca
## <chr> <chr> <chr>
## 1 9381267 0081568-68.2012.8.26.0050 São Paulo
## 2 8671548 2132739-15.2014.8.26.0000 Guarulhos
## 3 8634338 2204759-04.2014.8.26.0000 Osasco
## 4 8536605 2179832-71.2014.8.26.0000 Adamantina
## 5 8509346 2055376-49.2014.8.26.0000 Limeira
## 6 8490681 0014476-05.2014.8.26.0050 São Paulo
## 7 8466583 0067859-48.2014.8.26.0000 Suzano
## 8 8449087 0054802-60.2014.8.26.0000 Presidente Prudente
## 9 8429536 2128810-71.2014.8.26.0000 São Paulo
## 10 8331899 2002343-13.2015.8.26.0000 São Paulo
## # ... with 184,240 more rows, and 1 more variables: classe_assunto <chr>
d_cjsg %>%
select(n_processo, starts_with('data_'))
## # A tibble: 184,250 × 3
## n_processo data_julgamento data_registro
## <chr> <chr> <chr>
## 1 0081568-68.2012.8.26.0050 29/01/2015 27/04/2016
## 2 2132739-15.2014.8.26.0000 27/01/2015 04/08/2015
## 3 2204759-04.2014.8.26.0000 27/01/2015 22/07/2015
## 4 2179832-71.2014.8.26.0000 22/01/2015 16/06/2015
## 5 2055376-49.2014.8.26.0000 27/01/2015 02/06/2015
## 6 0014476-05.2014.8.26.0050 29/01/2015 27/05/2015
## 7 0067859-48.2014.8.26.0000 29/01/2015 19/05/2015
## 8 0054802-60.2014.8.26.0000 27/01/2015 13/05/2015
## 9 2128810-71.2014.8.26.0000 29/01/2015 06/05/2015
## 10 2002343-13.2015.8.26.0000 27/01/2015 29/03/2015
## # ... with 184,240 more rows
6.1.6 filter
- Parecido com
subset
. - Condições separadas por vírgulas é o mesmo que separar por
&
.
d_cjsg %>%
select(id, cd_acordao, comarca, relator = relatora) %>%
filter(comarca == 'São Paulo')
## # A tibble: 41,488 × 4
## id cd_acordao comarca relator
## <chr> <chr> <chr> <chr>
## 1 1 9381267 São Paulo Encinas Manfré
## 2 6 8490681 São Paulo Roberto Solimene
## 3 9 8429536 São Paulo Willian Campos
## 4 10 8331899 São Paulo Luis Soares de Mello
## 5 12 8317638 São Paulo Sérgio Mazina Martins
## 6 13 8314983 São Paulo Péricles Piza
## 7 14 8314866 São Paulo Péricles Piza
## 8 17 8293299 São Paulo Ivo de Almeida
## 9 19 8284691 São Paulo Edison Brandão
## 10 21 8274010 São Paulo Cesar Mecchi Morales
## # ... with 41,478 more rows
library(lubridate)
d_cjsg %>%
select(id, cd_acordao, comarca, data_julgamento, relator = relatora) %>%
filter(comarca %in% c('Campinas', 'Sorocaba') &
(day(dmy(data_julgamento)) >= 29 | day(dmy(data_julgamento)) < 25))
## # A tibble: 6,262 × 5
## id cd_acordao comarca data_julgamento relator
## <chr> <chr> <chr> <chr> <chr>
## 1 33 8221266 Sorocaba 29/01/2015 Alcides Malossi Junior
## 2 136 8211543 Campinas 29/01/2015 Walter da Silva
## 3 174 8211235 Sorocaba 22/01/2015 Walter da Silva
## 4 188 8211081 Sorocaba 29/01/2015 Walter da Silva
## 5 190 8211053 Campinas 29/01/2015 Walter da Silva
## 6 229 8206214 Sorocaba 29/01/2015 Ricardo Tucunduva
## 7 312 8194316 Sorocaba 29/01/2015 Poças Leitão
## 8 354 8193920 Campinas 29/01/2015 Sérgio Ribas
## 9 417 8193329 Campinas 29/01/2015 Poças Leitão
## 10 427 8193274 Sorocaba 29/01/2015 Poças Leitão
## # ... with 6,252 more rows
d_cjsg %>%
select(comarca) %>%
filter(str_detect(comarca, '^[gG]'))
## # A tibble: 6,463 × 1
## comarca
## <chr>
## 1 Guarulhos
## 2 Guarulhos
## 3 Guarulhos
## 4 Guarulhos
## 5 Guará
## 6 Guarulhos
## 7 Guarulhos
## 8 Guarulhos
## 9 Guarulhos
## 10 Guarulhos
## # ... with 6,453 more rows
6.1.7 mutate
- Parecido com
transform
, mas aceita várias novas colunas iterativamente. - Novas variáveis devem ter o mesmo
length
que onrow
do bd oridinal ou1
.
library(stringr)
d_cjsg %>%
select(id, n_processo, data_julgamento) %>%
mutate(ano_julgamento = year(dmy(data_julgamento)),
ano_proc = str_sub(n_processo, 12, 15),
ano_proc = as.numeric(ano_proc),
tempo_anos = ano_julgamento - ano_proc)
## # A tibble: 184,250 × 6
## id n_processo data_julgamento ano_julgamento ano_proc
## <chr> <chr> <chr> <dbl> <dbl>
## 1 1 0081568-68.2012.8.26.0050 29/01/2015 2015 2012
## 2 2 2132739-15.2014.8.26.0000 27/01/2015 2015 2014
## 3 3 2204759-04.2014.8.26.0000 27/01/2015 2015 2014
## 4 4 2179832-71.2014.8.26.0000 22/01/2015 2015 2014
## 5 5 2055376-49.2014.8.26.0000 27/01/2015 2015 2014
## 6 6 0014476-05.2014.8.26.0050 29/01/2015 2015 2014
## 7 7 0067859-48.2014.8.26.0000 29/01/2015 2015 2014
## 8 8 0054802-60.2014.8.26.0000 27/01/2015 2015 2014
## 9 9 2128810-71.2014.8.26.0000 29/01/2015 2015 2014
## 10 10 2002343-13.2015.8.26.0000 27/01/2015 2015 2015
## # ... with 184,240 more rows, and 1 more variables: tempo_anos <dbl>
6.1.8 arrange
- Simplesmente ordena de acordo com as opções.
- Utilizar
desc
para ordem decrescente.
library(stringr)
d_cjsg %>%
select(id, n_processo, data_julgamento) %>%
mutate(ano_julgamento = year(dmy(data_julgamento)),
ano_proc = str_sub(n_processo, 12, 15),
ano_proc = as.numeric(ano_proc)) %>%
mutate(tempo_anos = ano_julgamento - ano_proc) %>%
arrange(desc(tempo_anos))
## # A tibble: 184,250 × 6
## id n_processo data_julgamento ano_julgamento ano_proc
## <chr> <chr> <chr> <dbl> <dbl>
## 1 1797 0901097-67.1957.8.26.0050 30/04/2015 2015 1957
## 2 13650 0815784-50.1971.8.26.0050 12/11/2015 2015 1971
## 3 7222 9000001-18.1976.8.26.0309 16/07/2015 2015 1976
## 4 8228 9000001-74.1979.8.26.0224 23/02/2015 2015 1979
## 5 6512 0909882-46.1979.8.26.0050 26/05/2015 2015 1979
## 6 3439 9000001-81.1981.8.26.0005 26/02/2015 2015 1981
## 7 1469 0000014-17.1982.8.26.0292 29/01/2015 2015 1982
## 8 12850 0000784-59.1982.8.26.0114 02/07/2015 2015 1982
## 9 7040 0000019-02.1983.8.26.0584 27/01/2015 2015 1983
## 10 3920 2050003-20.1984.8.26.0281 26/02/2015 2015 1984
## # ... with 184,240 more rows, and 1 more variables: tempo_anos <dbl>
6.1.9 summarise
- Retorna um vetor de tamanho
1
a partir de uma conta com as variáveis. - Geralmente é utilizado em conjunto com
group_by
. - Algumas funções importantes:
n()
,n_distinct()
.
d_cjsg %>%
select(id, n_processo, comarca, data_julgamento, orgao_julgador) %>%
mutate(ano_julgamento = year(dmy(data_julgamento)),
ano_proc = str_sub(n_processo, 12, 15),
ano_proc = as.numeric(ano_proc)) %>%
mutate(tempo_anos = ano_julgamento - ano_proc) %>%
arrange(desc(tempo_anos)) %>%
group_by(comarca, orgao_julgador) %>%
summarise(n = n(),
media_anos = mean(tempo_anos),
min_anos = min(tempo_anos),
max_anos = max(tempo_anos)) %>%
filter(n > 5) %>%
arrange(desc(media_anos))
## Source: local data frame [4,351 x 6]
## Groups: comarca [271]
##
## comarca orgao_julgador n
## <chr> <chr> <int>
## 1 Piraju 2ª Câmara Criminal Extraordinária 8
## 2 José Bonifácio 6ª Câmara Criminal Extraordinária 6
## 3 Miguelópolis 2ª Câmara Criminal Extraordinária 6
## 4 Piedade 3ª Câmara Criminal Extraordinária 6
## 5 Valinhos 1ª Câmara Criminal Extraordinária 6
## 6 Lençóis Paulista 2ª Câmara de Direito Criminal 8
## 7 Pindamonhangaba 5ª Câmara Criminal Extraordinária 8
## 8 Praia Grande 6ª Câmara Criminal Extraordinária 8
## 9 Santa Bárbara D Oeste 4ª Câmara Criminal Extraordinária 7
## 10 Ituverava 3ª Câmara Criminal Extraordinária 6
## # ... with 4,341 more rows, and 3 more variables: media_anos <dbl>,
## # min_anos <dbl>, max_anos <dbl>
d_cjsg %>%
count(relatora, sort = TRUE) %>%
mutate(prop = n / sum(n), prop = scales::percent(prop))
## # A tibble: 111 × 3
## relatora n prop
## <chr> <int> <chr>
## 1 Sérgio Coelho 3424 1.86%
## 2 Miguel Marques e Silva 3352 1.82%
## 3 Poças Leitão 2859 1.55%
## 4 Walter da Silva 2834 1.54%
## 5 Francisco Bruno 2767 1.50%
## 6 Edison Brandão 2748 1.49%
## 7 Souza Nery 2739 1.49%
## 8 Carlos Bueno 2730 1.48%
## 9 Ivo de Almeida 2661 1.44%
## 10 Guilherme de Souza Nucci 2639 1.43%
## # ... with 101 more rows
6.1.10 gather
- “Empilha” o banco de dados
library(tidyr)
d_cjsg %>%
select(cd_acordao:data_registro) %>%
gather(key, value, -cd_acordao) %>%
arrange(cd_acordao)
## # A tibble: 737,000 × 3
## cd_acordao key value
## <chr> <chr> <chr>
## 1 8137574 n_processo 0209050-18.2013.8.26.0000
## 2 8137574 comarca São Paulo
## 3 8137574 data_julgamento 22/01/2015
## 4 8137574 data_registro 22/01/2015
## 5 8137600 n_processo 0016319-58.2014.8.26.0000
## 6 8137600 comarca São Paulo
## 7 8137600 data_julgamento 22/01/2015
## 8 8137600 data_registro 22/01/2015
## 9 8137628 n_processo 0104838-68.2005.8.26.0050
## 10 8137628 comarca São Paulo
## # ... with 736,990 more rows
6.1.11 spread
- “Joga” uma variável nas colunas
- É essencialmente a função inversa de
gather
d_cjsg %>%
distinct(cd_acordao, .keep_all = TRUE) %>%
select(cd_acordao:data_registro) %>%
gather(key, value, -cd_acordao) %>%
spread(key, value)
## # A tibble: 184,249 × 5
## cd_acordao comarca data_julgamento data_registro
## * <chr> <chr> <chr> <chr>
## 1 8137574 São Paulo 22/01/2015 22/01/2015
## 2 8137600 São Paulo 22/01/2015 22/01/2015
## 3 8137628 São Paulo 22/01/2015 22/01/2015
## 4 8137638 São Paulo 22/01/2015 22/01/2015
## 5 8137663 Espírito Santo do Pinhal 22/01/2015 22/01/2015
## 6 8137671 Presidente Venceslau 22/01/2015 22/01/2015
## 7 8137677 Paraguaçu Paulista 22/01/2015 22/01/2015
## 8 8137690 Guarulhos 22/01/2015 22/01/2015
## 9 8137695 Osasco 22/01/2015 22/01/2015
## 10 8137696 Americana 22/01/2015 22/01/2015
## # ... with 184,239 more rows, and 1 more variables: n_processo <chr>
6.1.12 Funções auxiliares
unite
junta duas ou mais colunas usando algum separador (_
, por exemplo).separate
faz o inverso deunite
, e uma coluna em várias usando um separador.
d_cjsg %>%
select(n_processo, classe_assunto) %>%
separate(classe_assunto, c('classe', 'assunto'), sep = ' / ',
extra = 'merge', fill = 'right') %>%
count(assunto, sort = TRUE)
## # A tibble: 287 × 2
## assunto n
## <chr> <int>
## 1 Tráfico de Drogas e Condutas Afins 30993
## 2 Roubo 17556
## 3 Roubo Majorado 17461
## 4 Crimes de Tráfico Ilícito e Uso Indevido de Drogas 13635
## 5 Furto Qualificado 13275
## 6 Pena Privativa de Liberdade 10801
## 7 Furto 9870
## 8 Progressão de Regime 7068
## 9 Receptação 5978
## 10 Crimes do Sistema Nacional de Armas 5675
## # ... with 277 more rows
6.1.13 Um pouco mais de transformação de dados
- Para juntar tabelas, usar
inner_join
,left_join
,anti_join
, etc. - Para realizar operações mais gerais, usar
do
. - Para retirar duplicatas, utilizar
distinct
.