Abrindo e Manipulando Dados

Entendendo o mundo de Big Data

Clique aqui para assistir o vídeo da aula online do dia 9 de abril de 2021. E o chat.

Manipulando Dados

Estamos trabalhando com um banco de dados, mas ele não está pronto para a análise que desejamos fazer. Por exemplo, as variáveis não contêm os indicadores relevantes, os nomes das variáveis não fazem sentido, a unidade de análise precisa ser mais agregada, queremos retirar alguns outliers etc. Como podemos ‘manipular’ um banco de dados para o tamanho, a estrutura e o conteúdo apropriado para a análise desejada?

Fazemos a manipulação da mesma forma que trabalhamos com os ingredientes de uma receita: executando ações para cortar, selecionar e combinar os ingredientes. Sempre começando com o nosso tibble (data.frame) e aplicamos ações (‘verbos’) que transformam o nosso banco de dados.

Na verdade, esta lógica de manipulação de dados baseada em ‘verbos’ é apenas uma abordagem no mundo flexível de R, e no futuro vamos ver alternativas. Por enquanto, vamos trabalhar com a abordagem de verbos do pacote tidyverse porque (i) é mais fácil para aprender, (ii) é mais sistemático, e (iii) é mais transparente para ler e entender do que outras abordagens.

Antes de começar, lembre-se de abrir o projeto com o qual você trabalhou no tutorial anterior (deve aparecer na lista no menu (‘Project:’) no canto superior à direita), ou um novo projeto se necessário. Em seguida, abra um novo arquivo de R Markdown (File -> New File -> R Markdown), e apague tudo exceto o cabeçalho:

---
title: "Examplo"
author: "Jonathan"
date: "1 de abril 2021"
output: html_document
---

Os códigos descritos no restante do tutorial só funcionam se você abrir a biblioteca do tidyverse (que já instalamos no tutorial anterior) num chunk inicial:

```{r}
library("tidyverse")
```

Também sugerimos instalar e abrir o pacote tidylog, que automaticamente fornece mais informação sobre cada uma das operações que executamos no tidyverse. Por isso, executamos uma vez só a instalação do pacote:

install.packages("tidylog")

E em seguida, adicionamos a biblioteca no início do nosso script:

```{r}
library("tidyverse")
library("tidylog")
```

1. Renomear Variáveis (Rename)

Começamos com uma transformação bem simples, mas se você já abriu um banco de dados com variáveis nomeadas como ‘hu52_lm_00’ você vai entender o valor dessa transformação. Cada coluna (variável) em nosso tibble sempre tem um nome, e podemos trocá-lo a qualquer momento.

Para inspecionar os nomes das variáveis num tibble, podemos simplesmente executar o nome do objeto no modo interativo e ver o que aparece na tabela abaixo do chunk ou no Console. Ou então, podemos usar a função names(). Vamos utilizar como exemplo de banco de dados os voos de Nova York, dados que usamos no tutorial anterior, lembrando que temos que abrir a biblioteca de voos primeiramente (se esqueceu dê uma olhada no tutorial 1).

 [1] "year"           "month"          "day"           
 [4] "dep_time"       "sched_dep_time" "dep_delay"     
 [7] "arr_time"       "sched_arr_time" "arr_delay"     
[10] "carrier"        "flight"         "tailnum"       
[13] "origin"         "dest"           "air_time"      
[16] "distance"       "hour"           "minute"        
[19] "time_hour"     

Note que o R descreve os índices (as posições na lista) dos nomes na esquerda.

Queremos renomear a variável arr_time para arrival_time - como faremos? Temos que aplicar o verbo e função rename() ao banco de dados flights. Agora temos um princípio fundamental da manipulação de dados no tidyverse: começamos com o substantivo (o objeto; o tibble) e depois aplicamos o verbo (a transformação; a função). Como em português: “A universidade [objeto] fechou [verbo]”.

Para conectar o substantivo com o verbo, usamos um símbolo bizarro que se chama o ‘pipe’: %>%. Não me pergunte o motivo para usar este símbolo; apenas Deus tem a resposta. A única coisa que importa é como a usar. O modelo é:

flights %>% rename()

Habilidade Básica de Programação: Pipes, %>% O pipe conecta um tibble a uma função. Pode ser traduzido como ‘e depois’, ou ‘then’ em inglês. Por exemplo, “pegue o banco de dados de flights, e depois aplique a função renomear”.

Podemos juntar vários pipes para combinar funções diferentes e gerar uma análise mais complexa. Por exemplo:

flights %>% rename() %>% outra_funcao() %>% mais_uma_funcao()


O código acima não faz nada porque ainda não especificamos qual variável renomear e o novo nome. Qual variável a renomear e o novo nome da variável são parâmetros da função rename, que tem um formato específico:

flights %>% rename(arrival_time = arr_time)

Qual o formato aqui? Dentro dos parênteses, colocamos o novo nome primeiro, depois o sinal de igual, depois o nome antigo/original. Se digitarmos o nome original errado, a função não vai funcionar e vai aparecer uma mensagem de erro. O nome novo pode ser diversas coisas (não abuse da sua criatividade aqui), mas evite começar com números e, por enquanto para simplificar, evite usar espaços (pode usar "_" em vez de um espaço).

Vamos inspecionar o nosso novo tibble renomeado:

flights

…O que aconteceu?? Porque você acha a variável em nosso tibble ainda tem o nome antigo `arr_time’?

Porque o nosso código não mudou nada: aplicar verbos não salva o novo tibble renomeado automaticamente. Efetivamente, o novo tibble renomeado desaparece no momento que é criado. Para salvar, temos que usar a seta de atribuição ao um novo objeto (se esqueceu, dê uma olhada no tutorial 1):

flights_renomeado <- flights %>% rename(arrival_time=arr_time)

flights_renomeado

Agora, o tibble de flights_renomeado tem a variável chamada arrival_time, correto?

Dependendo do nosso objetivo, às vezes faz sentido salvar o nosso objeto com o mesmo nome que ele tinha antes, sobrescrevendo o conteúdo dele, ao invés de criar um novo objeto toda vez que executamos uma função. (Pelo menos, isso economiza memória).

flights <- flights %>% rename(arrival_time=arr_time)

flights

Mais uma detalhe: será que para renomear colunas diversas temos que escrever a função rename() diversas vezes?

flights <- flights %>% rename(arrival_time=arr_time) %>%
  rename(departure_time=dep_time)

Podemos fazer isso, mas é mais eficiente fazer dentro da mesma função, separando as colunas por vírgula (e inserindo uma nova linha para deixar o código claro). Lembre-se da vírgula para separar cada renomeação, muitas vezes passamos para a linha de baixo e esquecemos a vírgula; quando rodamos o código aparece mensagem de erro e demoramos para descobrir que o único erro é a vírgula faltante.

flights <- flights %>% rename(arrival_time=arr_time,
                              departure_time=dep_time)

Observe que você pode receber um erro aqui - por que? Já renomeamos as variáveis acima e salvamos, então arr_time não existe mais em flights para renomear.

2. Selecionar Variáveis (Select)

Já aprendemos o formato para utilizar funções, e tudo o que vamos aprender daqui para frente possui o mesmo padrão. Quando temos colunas demais em nosso banco de dados, sempre ajuda focar nas variáveis mais relevantes, excluindo aquelas que não serão utilizadas. Para selecionar um subconjunto das variáveis (colunas) para manter no tibble, usamos o verbo select(). De novo, começamos com o tibble, o pipe, e finalmente o verbo, select:

flights %>% select(year, month, day)

Note que podemos selecionar várias variáveis usando uma vírgula para separar os nomes das variáveis. Fácil, certo?

Mas preste atenção - se você salvar o seu objeto com o mesmo nome do original, vai perder as outras variáveis definitivamente (ou pelo menos até que abra o banco de dados original novamente ou rode o script do início de novo):

flights <- flights %>% select(year, month, day)

3. Transformar Variáveis (Mutate)

E se quisermos criar novas variáveis? Isso é comum, por exemplo, quando queremos o PIB per capita e não simplesmente o PIB. Para isso, temos que pegar duas variáveis, PIB e população e dividir o primeiro pelo segundo. Em R, o verbo para realizar isso se chama mutate(). Ele permite a combinação, usando qualquer tipo de matématica que você desejar, de colunas que já existem no banco de dados (se quer trazer dados de fora, tem que usar um join que vamos discutir logo no futuro).

Como funciona? Como sempre, pegamos o nosso tibble relevante, depois o pipe, depois a função mutate(). Dentro dos paramêtros de mutate precisamos especificar o cálculo a ser realizado usando os nomes de colunas atuais, e o nome da nova variável (coluna) em que vamos guardar o resultado do cálculo. Por exemplo, se queremos dobrar o dep_delay:

flights <- flights %>% mutate(dep_delay_dobro=dep_delay*2)

Note que dentro do mutate, usamos o igual “=” em vez da flecha para salvar o resultado como uma nova variável.

Onde fica a nossa nova coluna? Na última posição à direita do tibble (última coluna do banco de dados).

Podemos combinar variáveis múltiplas para fazer cálculos mais complexos. Por exemplo, se por algum motivo eu quero saber metade da diferença entre o dep_time e arr_time:

flights <- flights %>% mutate(calculo=(arr_time-dep_time)/2)

Como na matemática, lembre-se que os parênteses importam. Então o que fizemos acima (arr_time-dep_time)/2 é diferente de arr_time-dep_time/2. Se quiser, teste para ter certeza.

Mais uma possibilidade: podemos transformar uma coluna atual sem criar uma nova coluna. Para fazer isso, é só renomear a coluna com o mesmo nome do original, dessa maneira sobrescrevemos o conteúdo original da coluna pelo novo conteúdo que calculamos. Por exemplo, podemos recalcular o dep_delay de minutos para segundos:

flights <- flights %>% mutate(dep_delay=dep_delay*60)

E finalmente, podemos usar funções dentro de mutate e não simplesmente símbolos matemáticos. No futuro, isso abre um mundo de possibilidades. Por enquanto, vamos apenas usar a função tolower() para mudar a origem (variável origin) do voo de maiúsculas para minúsculas:

flights <- flights %>% mutate(origin=tolower(origin))

Abra os dados para ver se deu certo a função tolower().

Habilidade Básica de Programação: Operações Matemáticas R serve como calculadora e é simples realizar operações matemáticas, seja com números ou com variáveis.

Soma:

x + y

Subtração:

x - y

Multiplicação

x * y

Divisão:

x / y

Potência:

x ^ y

Divisão inteira (sem resto):

x %/% y

Resto da divisão:

x %% y

4. Cortar/selecionar Observações (Slice)

Até agora, trabalhamos com manipulações de variáveis (colunas). Mas podemos também mexer com as observações (linhas). Podemos, por exemplo, limitar a nossa análise apenas para a quinta linha do banco de dados usando o verbo slice().

flights %>% slice(5)

Um pouco triste perder todo o resto da informação…, então, como selecionamos todas as primeiras cinco linhas?

flights %>% slice(1:5)

Habilidade Básica de Programação: Conjuntos de números Para selecionar observações ou outros elementos de objetos, temos que criar um vetor com os índices (as posições) dos elementos desejados. Um jeito de fazer isso é usando a nossa função para criar vetores, c():

linhas_desejadas <- c(1,4,5,8,22,169)

Agora, podemos usar este vetor, chamando ele por nome, dentro da função slice().

flights %>% slice(linhas_desejadas)

O R substituirá o objeto (o vetor) linhas_desejadas com os 6 números e devolverá um tibble das 6 linhas.

Também é possível selecionar as observações não desejadas, inserindo o sinal de menos, “-”, em frente ao número. O R devolve o tibble inteiro sem a linha identificada.

flights %>% slice(-1)

Compare o número de linhas do código acima com o número de linhas no tibble original de flights.

Para conjuntos de números mais sistemáticos, temos várias opções. Usamos os dois pontos para indicar um conjunto sequencial de números, por exemplo 10:20 significa o mesmo que c(10,11,12,13,14,15,16,17,18,19,20).

flights %>% slice(10:20)

Para conjuntos não-sequenciais mais sistemáticos, podemos usar a função seq(), que tem três parâmetros: valor inicial, valor final, e incremento. Por exemplo, para selecionar cada 10 linhas nas primeiras 100 linhas, usamos:

flights %>% slice(seq(from=1,
                      to=100,
                      by=10))

Quais os números que a função seq(from=1, to=100, by=10) devolve? Copie e cole a função no “Console” para ver o resultado. Aparece (1, 11, 21, 31, 41, 51, 61, 71, 81, 91).

Note que aqui usamos os nomes de cada parâmetro/argumento seguido por um sinal de igual e o valor relevante. Estes argumentos têm uma ordem oficial dentro da função, e se soubermos a ordem e especificarmos todos os argumentos, podemos evitar os nomes dos parâmetros/argumentos. O código abaixo é idêntico ao código acima:

flights %>% slice(seq(1,100,10))

Como podemos saber os nomes e a ordem dos argumentos? Consultamos o help da função:

?seq

5. Filtrar Observações (Filter)

Mais frequentemente, não importa a posição vertical (linha) da observação no conjunto de dados. Para limitar a nossa análise o que importa é o valor de uma variável. Por exemplo, podemos buscar apenas os dados da Ásia, do século 20, de mulheres, ou de homens acima de 18 anos de idade que moram em São Paulo.

Estes critérios podem ser aplicados usando o verbo filter(). Nos parâmetros de filter(), temos que especificar as condições do banco de dados final. O R vai avaliar se o parâmetro de cada observação é verdadeiro ou falso (TRUE ou FALSE), armazenando apenas as observações ‘verdadeiras’.

Em nosso banco de dados de voos, vamos selecionar apenas os voos do mês 6 (junho). Como definimos esta condição? Precisamos de três elementos:

  1. Nome de variável - aqui, o mês, month.
  2. Tipo de comparação - aqui, queremos selecionar um mês específico, então precisamos de uma igualdade que digitamos em R como ==. Sim, dois iguais juntos! Explicamos abaixo.
  3. Critério - aqui, qual mês? Nos dados, junho está codificado como número (int), então ‘6’.
flights %>% filter(month==6)

O resultado é um novo tibble com quantas linhas? Se o nosso filtro funcionou, o novo tibble deve ter bem menos observações (linhas) que o tibble original. Normalmente queremos salvar o tibble com outro nome, dado que ele representa, agora, um novo conjunto de observações:

flights_junho <- flights %>% filter(month==6)

Habilidade Básica de Programação: Operadores Relacionais (Comparativos)

Os operadores relacionais são seis em R:

Operador Descrição
1 == Igual
2 != Diferente
3 < Menor
4 > Maior
5 <= Menor ou igual
6 >= Maior ou igual

Simples. Alguns exemplos de uso básico de operadores abaixo. Rodar o código para verificar quais condições são verdadeiras ou falsas (TRUE ou FALSE).

42 == 41
42 != 41
(2 + 2) == (3 + 1)
(2 + 2) != (3 + 1)
5 > 3
5 < 3
42 > 42
42 < 41
42 >= 42
42 <= 41

Operadores relacionais também valem para textos:

"texto" == "texto"
"texto" == "texTo"
"texto" != "texto"

Note no segundo exemplo que o R é “case sensitive”, ou seja, diferencia maiúsculas de minúsculas ao comparar textos.

Textos também podem ser ordenados (lexicograficamente, isto é, alfabeticamente):

"a" > "b"
"a" < "b"
"A" < "b"
"A" > "a"

E valores lógicos? Veja se entende o que acontece nos exemplos abaixo:

TRUE == 1
FALSE == 0
TRUE > FALSE

Podemos comparar valores armazenados em variáveis da mesma maneira que fizemos nos exemplos até aqui:

x <- 5
y <- 10
x > y


Podemos combinar critérios diversos usando o símbolo de ‘e’, “&”:

flights_junho_5 <- flights %>% filter(month==6 & day==5)

Incluindo maior (>) e menor (<), podemos gerar comparações complexas, ex. todos os voos da manhã do dia 5 de julho:

flights_junho_5_manha <- flights %>% filter(month==6 & day==5 & dep_time<1200)

Habilidade Básica de Programação: Operadores Lógicos

Para combinar critérios múltiplos no mesmo filtro, temos que usar os operadores lógicos.

Operador Descrição
1 ! Não
2 & E
3 | Ou

Veja a tabela de possibilidades de combinação de duas proposições com a conjunção “&”:

Proposição 1 Proposição 2 Combinação
TRUE TRUE TRUE
TRUE FALSE FALSE
FALSE TRUE FALSE
FALSE FALSE FALSE

Se o valor atende às duas condições, então o resultado é TRUE. Se ao menos uma proposição é falsa, sob a conjunção “e”, então a combinação das proposições também é falsa.

Veja a tabela de possibilidades de combinação de duas proposições com a conjunção “ou”:

Proposição 1 Proposição 2 Combinação
TRUE TRUE TRUE
TRUE FALSE TRUE
FALSE TRUE TRUE
FALSE FALSE FALSE

Com esta nova flexibilidade, temos que pensar com cuidado para construir o filtro apropriado. E temos que usar os parênteses apropriados, porque a lista acima é em ordem de prioridade (como na matemática quando multiplicação acontece antes de adição, aqui “E” acontece antes de “OU”). Por exemplo, se quisermos todos os voos que atrasaram na chegada por mais de 50 minutos, e que decolaram antes das 5h ou que chegaram em Atlanta (ATL), temos que escrever assim:

flights %>% filter((dep_time<=500 | dest=="ATL") & arr_delay>=50)

O resultado é diferente do pedido quando tiramos os parênteses:

flights %>% filter(dep_time<=500 | dest=="ATL" & arr_delay>=50)

Note que o número de linhas é bem diferente. Aqui, pedimos para todos os voos que decolaram antes das 5h (se tivesse atraso ou não), juntado com um outro conjunto os voos que decolaram de Atlanta com atraso de 50 minutos na chegada.

É fácil pedir o inverso deste conjunto usando o símbolo para negação, !:

flights %>% filter(!((dep_time<=500 | dest=="ATL") & arr_delay>=50))

Combinando Manipulações

Frequentemente, limpar um banco de dados exige dezenas de transformações para construir o banco de dados apropriado para a nossa análise. A lógica e estrutura de cada ação acima nos permite combinar operações em sequência; em uma sequência de pipes e verbos. Depois de uma ação, simplesmente continuamos com mais um pipe (%>%) e a próxima ação.

flights %>% 
  rename(arrival_time=arr_time) %>% 
  mutate(dep_delay=dep_delay*60) %>%
  filter(month==6 & day==5) %>% 
  select(year, month, day, arrival_time, dep_delay)

É importante entender que depois de cada ação, o banco de dados encaminhado à próxima ação é o resultado da ação anterior. Então na linha final, select(year, month, day, arr_time, dep_delay) não funcionará, pois arr_time já foi renomeado para arrival_time e temos que fazer referência ao novo nome. Quando você enfrenta um erro num conjunto de código complexo, uma dica é rodar o seu código ação por ação em sequência, ex. selecionando flights %>% rename(arrival_time=arr_time) primeiro para saber se este componente dá um erro.

Voltando à analogia de preparar uma refeição, o código acima é uma receita: Pegue o banco de dados de flights, depois renomeie a variável arr_time, depois multiplique a variável dep_delay por 60, depois filtre as observações para aquelas do dia 5 de junho, depois selecione as cinco variáveis (year, month, day, arrival_time, dep_delay), e devolva o banco de dados final.

Note também que no código acima inserimos uma nova linha depois de cada pipe; isso não é necessário mas ajuda a organizar o código e deixá-lo mais fácil para ler e entender no futuro.

Exercício 1: Manipulando dados

Com essas novas habilidades, vamos preparar uma análise rápida do banco de dados flights com o objetivo de produzir um relatório em html no final. Gere uma tabela apropriada para cada critério:

  1. Os voos de United (carrier UA) que decolaram no dia 25 de janeiro.
Mostrar Código
flights %>%
    filter(carrier == "UA" & month == 1 & day == 25)
  1. Os voos de JetBlue (carrier B6) que decolaram com mais de 300 minutos de atraso de Newark (origin EWR).
Mostrar Código
flights %>%
    filter(carrier == "B6" & dep_delay > 300 & origin == "EWR")
  1. Calcule a velocidade dos voos que decolaram de LaGuardia (origin LGA) no dia 7 de setembro antes das 6h. Lembre-se que velocidade é a distância dividida por tempo. (Qual é a unidade desta velocidade?)
Mostrar Código
flights %>%
    filter(origin == "LGA" & month == 9 & day == 7 & dep_time < 600) %>%
    mutate(speed = distance/air_time)
  1. Uma tabela com apenas o atraso na chegada de todos os voos atrasados por pelo menos 60 minutos que partiram do aeroporto Newark e chegaram em Buffalo (BUF) no dia seis de todos os meses.
Mostrar Código
flights %>%
    filter(dest == "BUF" & origin == "EWR" & arr_delay >= 60 & day == 6) %>%
    select(arr_delay)
  1. Uma tabela dos números dos aviões (tailnum), destino, distância e a velocidade em milhas por hora para voos que voaram em maio pelo menos 1000 milhas ou com velocidade acima de 500 milhas por hora.
Mostrar Código
flights %>%
    mutate(velocidade = distance/(air_time/60)) %>%
    filter((distance > 1000 | velocidade > 500) & month == 5) %>%
    select(tailnum, dest, distance, velocidade)
  1. Prepare os resultados de todas as análises acima em tabelas usando a opção de R Markdown de df_print: paged (veja o Tutorial 1), e faça o knit do seu script de R markdown para produzir o relatório final.

Controlando o que Aparece no Relatório Final

Os nossos relatórios finais são profissionais e claros, mas ficam ‘técnicos’ quando mantemos as várias linhas de código e informações do R. Isso é importante se quiser documentar e comunicar exatamente como você analisou os dados, mas provavalmente o seu orientandor não tem interesse em saber como foi feito em detalhes. Como geramos um relatório ‘limpo’ para o público geral?

O R Markdown nos permite controlar os produtos de cada chunk individualmente. Existem pelo menos cinco tipos de produtos possíveis para cada chunk, e decidimos quais deles devem aparecer no relatório final com um argumento na linha inicial de cada chunk:

Tipo de Conteúdo Quero Não Quero
Código em si echo=TRUE echo=FALSE
Resultados da execução do código results=‘markup’ results=‘hide’
Erros error=TRUE error=FALSE
Avisos warning=TRUE warning=FALSE
Mensagens message=TRUE message=FALSE

O padrão (default) é para incluir todos os cinco tipos de conteúdo no relatório final. Mas na prática, normalmente não queremos mostrar para o leitor o código, erros, avisos e mensagens. Para cada chunk, podemos especificar as opções assim:

```{r, echo=FALSE, error=FALSE, warning=FALSE, message=FALSE}
600/30
```

Se compilamos o relatório com ‘Knit’, a única coisa que será impressa no documento final é o resultado do cálculo (20), nada do código ou o pensamento do R.

Porém, num relatório grande, teremos dezenas de chunks e fica chato especificar todas as opções para cada um dos chunks. Então uma alternativa é ajustar o padrão da nossa análise para que, por exemplo, echo=FALSE seja o padrão. O melhor jeito é adicionar um novo chunk no início do seu script com a seguinte linha:

```{r, echo=FALSE}
knitr::opts_chunk$set(echo=FALSE, error=FALSE, warning=FALSE, message=FALSE)
```

Isso indica para o R não imprimir o código original de nenhum chunk. Note que temos que usar echo=F na linha inicial deste chunk também para esconder esta linha de código porque o novo padrão só é aplicado depois da conclusão deste chunk.

Exercício 2: Relatórios Limpos

Experimente adicionar um chunk com essa linha acima (knitr::opts_chunk$set(echo=FALSE, error=FALSE, warning=FALSE, message=FALSE)) acima como o primeiro no seu relatório do Exercício 1, e ‘Knit’ de novo. Veja quão mais simples e bonito fica o seu relatório!

Abrindo Dados

Dados em arquivos textuais (.csv, .tsv, .txt)

Agora que estamos especialistas na manipulação de dados já disponíveis em R, queremos analisar dados mais interessantes e relevantes para a nossa própria pesquisa. Isso exige a abertura de arquivos externos; bancos de dados que criamos ou recebemos de outros estudos. Lembrando que o nosso script vai processar os comandos cada vez que é executado pelo botão ‘Knit’, então temos que incorporar a abertura de dados em código também, dentro do script.

Existem muitas funções para abrir arquivos de dados, mas, para simplificar, neste curso vamos nos concentrar em algumas das mais flexíveis, simples e úteis para trabalhar com dados ‘retangulares’ (.csv, .tsv, .txt). As funções são parte da biblioteca tidyverse que já abrimos.

Provavelmente a função mais usada é read_csv, que abre arquivos com extensão .csv. Em vez de abrir arquivos do nosso computador, também podemos abrir links online e, para simplificar, disponibilizamos vários arquivos em nosso repositório do github. Para começar, vamos salvar o url do link de um arquivo .csv como um objeto, file1, e abri-lo.

file1 <- "https://raw.githubusercontent.com/leobarone/ifch_intro_r/master/data/bf_amostra_hv.csv"
dados <- read_csv(file1)

dados’ deve aparecer como um objeto - um tibble - em seu ‘Environment’.

A função read_delim nos dá mais flexibilidade para lidar com tipos incomuns de arquivos. Por exemplo, podemos especificar o caractere usado para separar as colunas (por padrão, esta é a vírgula em read_csv, mas muitos dados brasileiros usam “;” como padrão, já que a vírgula é, no Brasil, um separador decimal):

dados <- read_delim(file1, 
                    delim = ",")

file_semi_colon <- "https://raw.githubusercontent.com/leobarone/ifch_intro_r/master/data/bf_amostra_hp.csv"
dados <- read_delim(file_semi_colon, 
                    delim = ";")

file_tab <- "https://raw.githubusercontent.com/leobarone/ifch_intro_r/master/data/bf_amostra_ht.csv"
dados <- read_delim(file_tab, 
                    delim = "\t")

O padrão de read_delim (e read_csv) é importar a primeira linha como o nome das variáveis. Se nossos dados não tiverem um header (cabeçalho, ou seja, nomes das variáveis na primeira linha), a primeira linha de dados se torna equivocadamente o nome das variáveis (inclusive os números, que aparecem antecedidos por um “X”). Para corrigir o problema utilizamos o argumento “col_names”, que deve ser igual a “FALSE” para os dados armazenados sem nomes de colunas, por exemplo:

file_sem_header <- "https://raw.githubusercontent.com/leobarone/ifch_intro_r/master/data/bf_amostra_nv.csv"
dados <- read_delim(file_sem_header, 
                    col_names = F, 
                    delim = ",")

Além dos valores lógicos, “col_names” também aceita um vetor com novos nomes para as colunas como argumento:

dados <- read_delim(file_sem_header, 
                    col_names = c("estado", "municipio_cod", "municipio_nome",
                                  "NIS", "transferido"),
                    delim = ",")

Por vezes, é interessante definir as classes das variáveis a serem importadas, para evitar novas transformações quando os dados forem importados. O argumento col_types deve ser uma sequência de caracteres onde “c” = “character”, “d” = “double” (numérico), “l” = “logical” e “i” = “integer” (números inteiros). Por exemplo:

dados <- read_delim(file1, 
                    delim = ",", 
                    col_types = "cicid")

Perceba que, quando abrimos os dados sem especificar o tipo da coluna, a função read_csv tenta identificá-los automaticamente.

Uma complexidade de abertura de dados numéricos brasileiros é o uso da vírgula como separador decimal e o ponto para indicar milhares. Assim, temos que especificar no argumento locale essas diferenças.

dados <- read_delim(file1, 
                    delim = ",", 
                    locale = locale(decimal_mark=",",grouping_mark="."))

Também podemos usar locale para especificar o formato da hora e o formato da data do arquivo que estamos lendo.

Finalmente, é comum termos problemas para abrir arquivos que contenham caracteres especiais, pois há diferentes formas do computador interpretar vogais acentuadas, cedilha, etc. O “encoding” de cada arquivo varia de acordo com o sistema operacional e aplicativo no qual foi gerado.

dados <- read_delim(file1, 
                    delim = ",", 
                    locale = locale(encoding='latin1'))

Para resolver este problema, informamos ao R o parâmetro encoding dentro do locale, que indica qual é o “encoding” esperado do arquivo.

Habilidade Básica de Programação: Encoding dos Arquivos

Infelizmente não há formas automáticas infalíveis de descobrir o “encoding” de um arquivo e é preciso conhecer como foi gerado – seja você quem produziu o arquivo ou se você teve acesso à documentação – ou partir para tentativa e erro. Alguns “encodings” comuns são “latin1”, “latin2”, “utf8” e “WINDOWS-1252”, mas há diversos outros. Se o arquivo com o qual estamos trabalhando não contém caracteres especiais, não é preciso fazer nada; o R vai processá-lo adequadamente.

O formato mais flexível, se pretende gerar os seus próprios dados, é UTF-8 (utf8).

Dados em arquivos de Excel

Editores de planilha são, em geral, a primeira ferramenta de análise de dados que aprendemos. Diversas organizações disponibilizam (infelizmente) seus dados em formato .xls ou .xlsx e muitos pesquisadores utilizam editores de planilha para construir bases de dados.

Vamos ver como obter dados em formato .xls ou .xlsx diretamente, sem precisar abrir os arquivos e exportá-los para um formato de texto.

Vamos trabalhar com readxl. Importe a biblioteca (não é preciso instalar, já está instalada):

Nosso exemplo será a Pesquisa Perfil dos Municípios Brasileiros de 2005, produzida pelo IBGE e apelidada de MUNIC. Diferentemente das demais funções deste tutorial, precisamos baixar o arquivo para o computador e acessá-lo localmente. É uma boa oportunidade para praticar. Faça o download diretamente no browser no site do IBGE e descompacte para o arquivo “Base 2005.xls” na pasta do seu projeto.

Note que um ganho enorme de trabalhar dentro de um projeto é que não precisamos nos preocupar com a especificação do endereço inteiro de cada arquivo (o “C:\Users\Documents\…”) - só usamos o nome do arquivo e o R acessa tudo na pasta do projeto. (Se for num sub-pasta, podemos especificar “Subpasta/Base 2005.xls”)

Com a função excel_sheets examinamos quais são as planilhas existentes do arquivo:

excel_sheets("Base 2005.xls")

No caso, temos 11 planilhas diferentes (e um bocado de mensagens de erro estranhas). O dicionário, para quem já trabalhou alguma vez com a MUNIC, não é uma base de dados, apenas textos espalhados entre células. As demais, no entanto, têm formato adequado para um tibble.

Vamos importar os dados da planilha “Variáveis externas”. As duas maneiras abaixo se equivalem:

# 1
externas <- read_excel("Base 2005.xls", "Variáveis externas")

# 2
externas <- read_excel("Base 2005.xls", 11)

A função read_excel aceita os argumentos “col_names” e “col_types” tal como as funções de importação do pacote readr. Observe que o R não se importa e não lembra como o arquivo foi aberto - quando aberto por read_csv ou read_excel ou outra função, o tibble em R é idêntico.

Dados de SPSS, Stata e SAS

O R é bastante flexível quanto à importação de dados de outros softwares estatísticos. Para este fim há também um pacote haven, que é, advinhe só, parte do tidyverse.

Basicamente, há cinco funções de importação de dados em haven: read_sas, para dados em SAS; read_stata e read_dta, idênticas, para dados em formato .dta gerados em Stata; e read_sav e read_por, uma para cada formato de dados em SPSS. O uso, como era de se esperar, é bastante similar ao que vimos no tutorial todo.

Vamos usar como exemplo o Latinobarômetro 2015, que está disponível para SAS, Stata e SPSS. Vamos fazer o processo manual de baixar os dados da página ‘data bank’, e descompactar os arquivos de 2015. Vamos ignorar SAS por razões que não interessam agora e por não ser uma linguagem popular nas ciências sociais.

Vejamos o uso das funções em arquivos de diferentes formatos:

# SPSS
latino_barometro_spss <- read_spss("Latinobarometro_2015_Eng.sav")

# Stata
latino_barometro_stata <- read_stata("Latinobarometro_2015_Eng.dta")

Simples assim.

Há critérios de conversão de variáveis categóricas, rótulos e etc, adotados pelo R ao importar arquivos de outras linguagens, mas você pode descobri-los testando sozinho/a.

Exercício 3: Abrindo Dados Eleitorais

  1. Escolha um banco de dados (qualquer arquivo único) da aba ‘Resultados’ do site do Tribunal Superior Eleitoral aqui, baixá-lo e dê unzip nele.

  2. Use uma função apropriada para abrir o arquivo em R.

Mostrar Código
data <- read_delim("arquivo.txt", delim = ";", locale = locale(encoding = "latin1"))
  1. Use o arquivo leiame.pdf que fica no zip com o arquivo do TSE para identificar o encoding dos dados, e os nomes das variáveis. Incorpore esta informação na abertura do arquivo.
Mostrar Código
data <- read_delim("arquivo.txt", delim = ";", locale = locale(encoding = "latin1"), 
    col_names = c("Variavel_1", "Variavel_2", "..."))
  1. Crie uma tabela bonita em R Markdown dos dados do TSE, e verifique que o número de colunas e observações fazem sentido.

  2. Tente manipular a base utilizando as funções que aprendemos no tutorial de hoje para selecionar colunas e observações específicas.


Leitura para Tutorial 3

Antes da próxima aula, por favor leia R 4 Data Science, Capítulos 12, 15, 27