3 Lendo os dados

Após o entendimento do problema/projeto que se resolverá com a ciência de dados, será necessário fazer com que o R leia os dados. Seja lá qual for o assunto do projeto, é muito importante garantir uma boa fonte de dados. Dados ruins, inconsistentes, não confiáveis ou mal formatados podem gerar muita dor de cabeça para o analista.

3.1 Tipos de Estrutura dos Dados

Os dados podem ser apresentados de diversas maneiras, não existe um padrão único para a difusão ou divulgação. Sendo assim, é bom que você esteja preparado para lidar com qualquer tipo de estrutura de dados.

Existem diversas classificações de estrutura de dados. Vamos utilizar uma classificação mais generalista, que diz respeito a como os dados são disponibilizados. Sendo assim, podemos classificar os dados em três grandes tipos quanto à sua estrutura ou forma: dados estruturados, semiestruturados e não estruturados.

3.1.1 Dados Estruturados

Talvez seja o formato de dados mais fácil de se trabalhar no R. São conjuntos de informações organizadas em colunas (atributos, variáveis, features etc.) e linhas (registros, itens, observações etc.). São dados mais comumente encontrados diretamente em bancos de dados, arquivos com algum tipo de separação entre as colunas, Excel, arquivos com campos de tamanho fixo etc.

3.1.2 Dados Não Estruturados

Como o nome diz, estes dados não têm uma estrutura previsível, ou seja, cada conjunto de informações possui uma forma única. Geralmente são arquivos com forte teor textual. Não podemos dizer que são dados “desorganizados”, e sim que são organizações particulares para cada conjunto de informações. Podemos citar, por exemplo, e-mails, twitters, PDF, imagens, vídeos etc.

Analisar este tipo de dado é muito mais complexo e exige conhecimento avançado em mineração de dados. Apesar disso, é o tipo de dado mais abundante na realidade.

3.1.3 Dados Semiestruturados

São dados que também possuem uma organização fixa, porém não seguem o padrão de estrutura linha/coluna, ou seja, seguem uma estrutura mais complexa e flexível, geralmente hierárquica, estruturada em tags ou marcadores de campos. São exemplos de arquivos semiestruturados: JSON, XML, HTML, YAML etc. É o formato mais usado em troca de dados pela internet e consumo de Application programming interface (API). Dados semiestruturados, algumas vezes, são facilmente transformados em dados estruturados.

3.2 Definindo o Local dos Dados

O R sempre trabalha com o conceito de Working direcotry, ou seja, uma pasta de trabalho onde vai “ler” e “escrever” os dados. Para verificar qual o diretório que o R está “olhando”, utilize o seguinte comando:

getwd() #Get Working Directory

Para informar ao R em qual pasta ele deve ler os arquivos, utilizamos o comando set working directory, que muda o diretório padrão do R para leitura e escrita:

setwd('D:/caminho/do/arquivo/arquivo.csv')

3.3 Pacote para leitura dos dados

O R base possui funções para a leitura dos principais tipos de arquivos. Um outro pacote específico, e muito bom para isso, é o readr. O Tidyverse inclui o carregamento do pacote readr.

Diversos tipos de arquivos são lidos pelo R: Comma-Separated Values (csv), Excel, arquivos separados por delimitadores, colunas de tamanho fixo etc. Talvez o tipo de arquivo (estruturado) mais comum hoje em dia, e mais simples de trabalhar, seja o csv. Começaremos a importar dados com arquivos csv.

library(tidyverse) # já carrega o readr
#ou
library(readr)

Vamos importar um csv chamado senado.csv. Caso o arquivo esteja em seu working directory (getwd()), basta passar apenas o nome do arquivo para a função, caso contrário será necessário informar todo o caminho até a pasta do arquivo. Usamos o read_csv() para fazer isso.

senado <- read_csv("senado.csv")

Esse comando carrega o conteúdo do arquivo senado.csv para o objeto (variável) senado. Após o carregamento, começaremos a investigar o conteúdo desse objeto: os dados.

O head e o tail são funções para ver a “cabeça” e o “rabo” dos seus dados, ou seja, o começo e o fim das amostras. É muito importante sempre observar a “aparência” dos dados após o carregamento. Essa observação ajuda a identificar erros básicos no carregamento, possibilitando ajustes o quanto antes, impedindo que esses erros se propaguem. Repare que na primeira linha temos os nomes das colunas e, em seguida, os registros.

head(senado)
## # A tibble: 6 x 15
##   VoteNumber  SenNumber     SenatorUpper  Vote Party GovCoalition State
##        <int>      <chr>            <chr> <chr> <chr>        <lgl> <chr>
## 1    2007001 PRS0002/07    FLEXA RIBEIRO     S  PSDB        FALSE    PA
## 2    2007001 PRS0002/07  ARTHUR VIRGILIO     S  PSDB        FALSE    AM
## 3    2007001 PRS0002/07      FLAVIO ARNS     N    PT         TRUE    PR
## 4    2007001 PRS0002/07 MARCELO CRIVELLA     S   PRB         TRUE    RJ
## 5    2007001 PRS0002/07      JOAO DURVAL     N   PDT        FALSE    BA
## 6    2007001 PRS0002/07       PAULO PAIM     S    PT         TRUE    RS
## # ... with 8 more variables: FP <int>, Origin <int>, Contentious <int>,
## #   PercentYes <dbl>, IndGov <chr>, VoteType <int>, Content <chr>,
## #   Round <int>
tail(senado)
## # A tibble: 6 x 15
##   VoteNumber  SenNumber       SenatorUpper  Vote Party GovCoalition State
##        <int>      <chr>              <chr> <chr> <chr>        <lgl> <chr>
## 1    2010027 PLC0010/10       EDISON LOBAO     S  PMDB         TRUE    MA
## 2    2010027 PLC0010/10    EDUARDO SUPLICY     S    PT         TRUE    SP
## 3    2010027 PLC0010/10 JARBAS VASCONCELOS     N  PMDB         TRUE    PE
## 4    2010027 PLC0010/10     MARISA SERRANO     S  PSDB        FALSE    MS
## 5    2010027 PLC0010/10 EPITACIO CAFETEIRA     S   PTB        FALSE    MA
## 6    2010027 PLC0010/10      INACIO ARRUDA     S PCdoB         TRUE    CE
## # ... with 8 more variables: FP <int>, Origin <int>, Contentious <int>,
## #   PercentYes <dbl>, IndGov <chr>, VoteType <int>, Content <chr>,
## #   Round <int>

Outros comandos muito importantes para começar a investigar os dados são o str(), o class() e o summary().

Para verificar o tipo do objeto, ou seja, sua classe, utilize:

class(senado)
## [1] "tbl_df"     "tbl"        "data.frame"

Já para verificar a estrutura do objeto, ou seja, seus campos (quando aplicável), insira:

str(senado) #STRucture
## Classes 'tbl_df', 'tbl' and 'data.frame':    9262 obs. of  15 variables:
##  $ VoteNumber  : int  2007001 2007001 2007001 2007001 2007001 2007001 2007001 2007001 2007001 2007001 ...
##  $ SenNumber   : chr  "PRS0002/07" "PRS0002/07" "PRS0002/07" "PRS0002/07" ...
##  $ SenatorUpper: chr  "FLEXA RIBEIRO" "ARTHUR VIRGILIO" "FLAVIO ARNS" "MARCELO CRIVELLA" ...
##  $ Vote        : chr  "S" "S" "N" "S" ...
##  $ Party       : chr  "PSDB" "PSDB" "PT" "PRB" ...
##  $ GovCoalition: logi  FALSE FALSE TRUE TRUE FALSE TRUE ...
##  $ State       : chr  "PA" "AM" "PR" "RJ" ...
##  $ FP          : int  2 2 2 2 2 2 2 2 2 2 ...
##  $ Origin      : int  11 11 11 11 11 11 11 11 11 11 ...
##  $ Contentious : int  0 0 0 0 0 0 0 0 0 0 ...
##  $ PercentYes  : num  85.5 85.5 85.5 85.5 85.5 ...
##  $ IndGov      : chr  "S" "S" "S" "S" ...
##  $ VoteType    : int  1 1 1 1 1 1 1 1 1 1 ...
##  $ Content     : chr  "Creates the Senate Commission of Science, Technology, Innovation, Communication, and Information Technology (CCT)." "Creates the Senate Commission of Science, Technology, Innovation, Communication, and Information Technology (CCT)." "Creates the Senate Commission of Science, Technology, Innovation, Communication, and Information Technology (CCT)." "Creates the Senate Commission of Science, Technology, Innovation, Communication, and Information Technology (CCT)." ...
##  $ Round       : int  1 1 1 1 1 1 1 1 1 1 ...
##  - attr(*, "spec")=List of 2
##   ..$ cols   :List of 15
##   .. ..$ VoteNumber  : list()
##   .. .. ..- attr(*, "class")= chr  "collector_integer" "collector"
##   .. ..$ SenNumber   : list()
##   .. .. ..- attr(*, "class")= chr  "collector_character" "collector"
##   .. ..$ SenatorUpper: list()
##   .. .. ..- attr(*, "class")= chr  "collector_character" "collector"
##   .. ..$ Vote        : list()
##   .. .. ..- attr(*, "class")= chr  "collector_character" "collector"
##   .. ..$ Party       : list()
##   .. .. ..- attr(*, "class")= chr  "collector_character" "collector"
##   .. ..$ GovCoalition: list()
##   .. .. ..- attr(*, "class")= chr  "collector_logical" "collector"
##   .. ..$ State       : list()
##   .. .. ..- attr(*, "class")= chr  "collector_character" "collector"
##   .. ..$ FP          : list()
##   .. .. ..- attr(*, "class")= chr  "collector_integer" "collector"
##   .. ..$ Origin      : list()
##   .. .. ..- attr(*, "class")= chr  "collector_integer" "collector"
##   .. ..$ Contentious : list()
##   .. .. ..- attr(*, "class")= chr  "collector_integer" "collector"
##   .. ..$ PercentYes  : list()
##   .. .. ..- attr(*, "class")= chr  "collector_double" "collector"
##   .. ..$ IndGov      : list()
##   .. .. ..- attr(*, "class")= chr  "collector_character" "collector"
##   .. ..$ VoteType    : list()
##   .. .. ..- attr(*, "class")= chr  "collector_integer" "collector"
##   .. ..$ Content     : list()
##   .. .. ..- attr(*, "class")= chr  "collector_character" "collector"
##   .. ..$ Round       : list()
##   .. .. ..- attr(*, "class")= chr  "collector_integer" "collector"
##   ..$ default: list()
##   .. ..- attr(*, "class")= chr  "collector_guess" "collector"
##   ..- attr(*, "class")= chr "col_spec"

Para verificar estatísticas básicas do objeto (média, mediana, quantis, mínimo, máximo etc.), quando aplicáveis:

summary(senado)
##    VoteNumber       SenNumber         SenatorUpper      
##  Min.   :2007001   Length:9262        Length:9262       
##  1st Qu.:2008006   Class :character   Class :character  
##  Median :2009003   Mode  :character   Mode  :character  
##  Mean   :2008483                                        
##  3rd Qu.:2009048                                        
##  Max.   :2010027                                        
##      Vote              Party           GovCoalition       State          
##  Length:9262        Length:9262        Mode :logical   Length:9262       
##  Class :character   Class :character   FALSE:3480      Class :character  
##  Mode  :character   Mode  :character   TRUE :5782      Mode  :character  
##                                                                          
##                                                                          
##                                                                          
##        FP            Origin        Contentious        PercentYes     
##  Min.   :1.000   Min.   : 1.000   Min.   :0.00000   Min.   :  2.174  
##  1st Qu.:2.000   1st Qu.: 1.000   1st Qu.:0.00000   1st Qu.: 66.667  
##  Median :2.000   Median : 2.000   Median :0.00000   Median : 96.078  
##  Mean   :1.878   Mean   : 2.595   Mean   :0.01781   Mean   : 82.509  
##  3rd Qu.:2.000   3rd Qu.: 4.000   3rd Qu.:0.00000   3rd Qu.: 98.148  
##  Max.   :2.000   Max.   :11.000   Max.   :1.00000   Max.   :100.000  
##     IndGov             VoteType       Content              Round      
##  Length:9262        Min.   :1.000   Length:9262        Min.   :1.000  
##  Class :character   1st Qu.:1.000   Class :character   1st Qu.:1.000  
##  Mode  :character   Median :1.000   Mode  :character   Median :1.000  
##                     Mean   :1.159                      Mean   :1.358  
##                     3rd Qu.:1.000                      3rd Qu.:2.000  
##                     Max.   :2.000                      Max.   :4.000

Acontece que nem sempre o separador será o ;, típico do csv. Nesse caso será necessário usar o read_delim(), onde você pode informar qualquer tipo de separador. Outro tipo de arquivo bastante comum é o de colunas com tamanho fixo (fixed width), também conhecido como colunas posicionais. Nesse caso, será necessário usar o read_fwf() informando o tamanho de cada coluna.

Exemplo:

#lendo arquivo com delimitador #
read_delim('caminho/do/arquivo/arquivo_separado_por#.txt', delim = '#')

#lendo arquivo de coluna fixa
#coluna 1 de tamanho 5, coluna 2 de tamanho 2 e coluna 3 de tamanho 10
read_fwf('caminho/do/arquivo/arquivo_posicional.txt', col_positions = fwf_widths(c(5, 2, 10), c("col1", "col2", "col3")))

No capítulo a seguir exploraremos melhor os tipos de objetos mais comuns no R.

3.4 Exercícios:

  1. Leia o arquivo TA_PRECOS_MEDICAMENTOS.csv, cujo separador é uma barra |.

  2. Leia o arquivo de colunas fixas fwf-sample.txt, cuja primeira coluna (nomes) tem tamanho vinte, a segunda (estado) tem tamanho dez e a terceira (código) tem tamanho doze.

  3. Investigue os parâmetros das funções de leitura do R base: read.csv(), read.delim() e read.fwf(). Notou as diferenças das funções do readr?