3 Tibbles x Data frames

“Famílias felizes são todas iguais; toda família infeliz é infeliz à sua maneira.” – Leo Tolstoi

O que é um tibble? Tibbles são similares aos data frames, porém diferentes em dois aspectos: impressão e indexação

Na impressão no console, os tibbles apresentam apenas as dez primeiras linhas e todas as colunas que cabem na tela, tornando mais fácil o trabalho com grandes volumes de dados. Além disso, cada coluna apresenta o seu tipo, algo semelhante ao apresentado quando utilizamos a função str(). A segunda diferença, não menos importante, é a forma de indexação. Para indexar um tibble devemos utilizar o nome completo da variável que desejamos. Caso contrário, ocorrerá um erro.

Ainda sobre a indexação, sempre que indexarmos um tibble usando [, o resultado será outro tibble. Usando [[ o resultados será um vetor.

Em síntese, data frames são tabelas de dados. Em seu formato, são bem parecidos com as matrizes, no entanto, possuem algumas diferenças significativas. Podemos idealizar os data frames como sendo matrizes em que cada coluna pode armazenar um tipo de dado diferente. Logo, estamos lidando com um objeto bem mais versátil do que as matrizes e os vetores.

Uma das funções básicas mais importantes para começarmos a trabalhar com data frames é a str(). Essa função dá uma visão clara da estrutura do nosso objeto, bem como informa os tipos de dados existentes.

A função View() chama um visualizador de dados no estilo de planilhas em um objeto R. Semelhante a planilha do excel.

Os argumentos da função são: x um objeto do R que pode ser coagido a um quadro de dados. E title, título para a janela do visualizador. O padrão é o nome de x prefixado.

3.1 O que é Dados organizados?

“Os conjuntos de dados organizados são todos iguais, mas todos os conjuntos de dados confusos são confusos à sua maneira.” – Hadley Wickham

Costuma-se dizer que 80% da análise de dados é gasta no processo de limpeza e preparação os dados (Dasu e Johnson 2003). A preparação de dados não é apenas um primeiro passo, mas deve ser repetidos muitos ao longo da análise, à medida que novos problemas surgem ou novos dados são coletados.Você vai precisar instalar os pacotes tidyr, devtools e DSR. Para instalar tidyr e devtools, abra o RStudio e execute o comando:

DSR é uma coleção de conjuntos de dados. Para instalar DSR, execute o comando:

Os dados tabulares podem ser organizados de várias maneiras. Os conjuntos de dados abaixo mostram os mesmos dados organizados de quatro maneiras diferentes, sendo que possuem as mesmas variáveis: país, ano, população e casos. Mas cada conjunto organiza os valores em forma de layout diferente. Vejamos essas tabelas de dados seguintes:

## 
## Attaching package: 'DSR'
## The following objects are masked from 'package:tidyr':
## 
##     population, table1, table2, table3, table5, who
## # A tibble: 6 x 4
##   country      year  cases population
##   <fct>       <int>  <int>      <int>
## 1 Afghanistan  1999    745   19987071
## 2 Afghanistan  2000   2666   20595360
## 3 Brazil       1999  37737  172006362
## 4 Brazil       2000  80488  174504898
## 5 China        1999 212258 1272915272
## 6 China        2000 213766 1280428583
## # A tibble: 12 x 4
##    country      year key             value
##    <fct>       <int> <fct>           <int>
##  1 Afghanistan  1999 cases             745
##  2 Afghanistan  1999 population   19987071
##  3 Afghanistan  2000 cases            2666
##  4 Afghanistan  2000 population   20595360
##  5 Brazil       1999 cases           37737
##  6 Brazil       1999 population  172006362
##  7 Brazil       2000 cases           80488
##  8 Brazil       2000 population  174504898
##  9 China        1999 cases          212258
## 10 China        1999 population 1272915272
## 11 China        2000 cases          213766
## 12 China        2000 population 1280428583
## # A tibble: 6 x 3
##   country      year rate             
##   <fct>       <int> <chr>            
## 1 Afghanistan  1999 745/19987071     
## 2 Afghanistan  2000 2666/20595360    
## 3 Brazil       1999 37737/172006362  
## 4 Brazil       2000 80488/174504898  
## 5 China        1999 212258/1272915272
## 6 China        2000 213766/1280428583

O último conjunto de dados é uma coleção de duas tabelas.

## # A tibble: 3 x 3
##   country     `1999` `2000`
##   <fct>        <int>  <int>
## 1 Afghanistan    745   2666
## 2 Brazil       37737  80488
## 3 China       212258 213766
## # A tibble: 3 x 3
##   country         `1999`     `2000`
##   <fct>            <int>      <int>
## 1 Afghanistan   19987071   20595360
## 2 Brazil       172006362  174504898
## 3 China       1272915272 1280428583

R segue um conjunto de convenções que tornam um layout de dados tabulares muito mais fácil de trabalhar do que outros. Seus dados serão mais fáceis de trabalhar no R se seguirem três regras:

  • 1.Cada variável no conjunto de dados é colocada em sua própria coluna;
  • 2.Cada observação é colocada em sua própria linha;
  • 3.Cada valor é colocado em sua própria célula.

Os dados que satisfazem essas regras são conhecidos como dados organizados. Observe que table1 são dados organizados.

Essas três regras estão inter-relacionadas, porque é impossível satisfazer apenas duas das três. Essa inter-relação leva a um conjunto ainda mais simples de instruções práticas:

  • Coloque cada conjunto de dados em um tibble;

  • Coloque cada variável em uma coluna.

Em table1, cada variável é colocada em sua própria coluna, cada observação em sua própria linha e cada valor em sua própria célula.

Por que garantir que seus dados estejam organizados? Existem duas vantagens principais:

  • Há uma vantagem geral em escolher uma maneira consistente de armazenar dados. Se você possui uma estrutura de dados consistente, é mais fácil aprender as ferramentas que funcionam com ela porque elas têm uma uniformidade subjacente;

  • Há uma vantagem específica em colocar variáveis em colunas porque permite que a natureza vetorizada de R seja eficiente. Você aprenderá nas funções mutate e summary, a maioria das funções R internas trabalha com vetores de valores. Isso faz com que a transformação de dados organizados pareça particularmente natural.

3.2 Operador pipe %>%

O pacote magrittr tem dois objetivos: diminuir o tempo de desenvolvimento e melhorar a legibilidade e a manutenção do código. Para começar a utilizar o pipe, instale e carregue o pacote magrittr.

## 
## Attaching package: 'magrittr'
## The following object is masked from 'package:purrr':
## 
##     set_names
## The following object is masked from 'package:tidyr':
## 
##     extract

Tubulação básica:

  • x %>% f é equivalente a f(x);
  • x %>% f(y) é equivalente a f(x, y);
  • x %>% f %>% g %>% h é equivalente a h(g(f(x))).

O operador do pipeline %>% é muito útil para reunir várias funções em uma sequência de operações. Os tubos são uma ferramenta poderosa para expressar claramente as operações. O pipe, %>% vem do pacote magrittr de Stefan Milton Bache. Pacotes no tidyverse carregam %>% automaticamente, para que normalmente não carregue o magrittr explicitamente. Observe abaixo que toda vez que desejamos aplicar mais de uma função, a sequência é ocultada em uma sequência de chamadas de funções aninhadas difíceis de ler, ou seja:

third(second(first(x)))

Esse aninhamento não é uma maneira natural de pensar em uma sequência de operações. O %>% permite que você encadeie operações da esquerda para a direita, ou seja:

first(x) %>% second() %>% third()

Por exemplo:

## [1]  3.3  1.8  1.6  0.5  0.3  0.1 48.8  1.1
## [1]  3.3  1.8  1.6  0.5  0.3  0.1 48.8  1.1

Em resumo, aqui estão quatro razões pelas quais você deve usar tubos ou pipe no R:

  • Estruturara a sequência de suas operações de dados da esquerda para a direita, ao contrário de dentro para fora;

  • evita chamadas de função aninhadas;

  • minimiza a necessidade de variáveis locais e definições de funções;

  • facilita a adição de etapas em qualquer lugar da sequência de operações.

Mesmo sendo %>% o operador de tubulação (principal) do pacote magrittr, existem alguns outros operadores que fazem parte do mesmo pacote:

Ao trabalhar com tubos mais complexos, às vezes é útil chamar uma função por seus efeitos colaterais. Talvez você queira imprimir o objeto atual, plotá-lo ou salvá-lo em disco. Muitas vezes, essas funções não retornam nada, efetivamente encerrando o pipe.

Para contornar esse problema, usar-se o tubo “tee”. %T>% funciona como %>% exceto que retorna o lado esquerdo em vez do lado direito. É chamado de “tee” porque é como um tubo em forma de T literal.

##  NULL

##  num [1:50, 1:2] -0.4813 0.4946 -0.0852 -1.5671 0.7604 ...

Para mais informações sobre o pipe, outros operadores relacionados e exemplos de utilização, visite a página Ceci n’est pas un pipe. Ou consulte a vinheta do pacote vignette("magrittr").

3.3 Breve Introdução ao tidyr

O pacote tidyr tem como principal objetivo transformar um data frame para o formato tidy, ou limpo.

De acordo com as regras ditas anteriormente, um dado limpo/organizado é aquele com formato long, ou seja, com mais linhas. O outro formato é chamado de wide, com mais colunas. No caso deste exemplo, ano é uma variável, logo é necessário existir uma coluna com os valores de ano. O valor relacionado a UF naqueles anos também é outra variável, então precisa de uma coluna pra representá-lo. Além disso, a própria UF precisa de uma coluna.

O tidyr possui duas funções principais:

gather = amontoar: Transforma um tibble wide em long, ou seja, transforma os dados no formato tidy.

spread = esparramar: Transforma um tibble long em wide, ou seja, transforma dados que estão no formato tidy em formato não tidy.

Além disso, existem duas funções que podem ser importantes na nossa análise: separate e unite, que separa uma coluna em duas e vice versa.

Utilizando o conjunto de dados storms do pacote EDAWR, que descreve a velocidades máximas do vento para seis furacões no Atlântico.

## 
## Attaching package: 'EDAWR'
## The following object is masked from 'package:DSR':
## 
##     population
## The following object is masked from 'package:dplyr':
## 
##     storms
## The following objects are masked from 'package:tidyr':
## 
##     population, who
##     storm wind pressure       date
## 1 Alberto  110     1007 2000-08-03
## 2    Alex   45     1009 1998-07-27
## 3 Allison   65     1005 1995-06-03
## 4     Ana   40     1013 1997-06-30
## 5  Arlene   50     1010 1999-06-11
## 6  Arthur   45     1010 1996-06-17

Como você pode ver, toda variável (nome da tempestade, vento, pressão, data) tem sua própria coluna e toda observação é salva em sua própria linha.

Como você pode ver, toda variável (nome da tempestade, vento, pressão, data) tem sua própria coluna e toda observação é salva em sua própria linha.

##   country  2011  2012  2013
## 1      FR  7000  6900  7000
## 2      DE  5800  6000  6200
## 3      US 15000 14000 13000

O conjunto de dados cases têm três variáveis: o código do país em cada linha, o ano em cada coluna e uma contagem para cada combinação de linha e colunas. Como você pode ver, essa estrutura não está em conformidade com as características de um conjunto de dados organizado mencionado acima.

Vamos dar uma olhada em outro exemplo de um conjunto de dados não arrumado chamado poluição:

##       city  size amount
## 1 New York large     23
## 2 New York small     14
## 3   London large     22
## 4   London small     16
## 5  Beijing large    121
## 6  Beijing small     56

Aqui temos três variáveis: nomes de cidades, quantidade de partículas pequenas e quantidade de partículas grandes que cada cidade possui (indice de qualidade do ar). Novamente, isso não está em conformidade com as características de um conjunto de dados organizado. A próxima figura resume graficamente a estrutura dos três conjuntos de dados:

3.4 Função gather()

Se procurarmos a documentação para esta função, podemos encontrar: “usa o gather() quando percebe que possui colunas que não são variáveis.” Esta declaração se aplica ao conjunto de dados cases descrito acima. Então, vamos tentar arrumar usando a gather(). A função gather() retorna um tibble com duas colunas, por padrão, isso se não inserirmos nenhum parâmetro além do tibble.

O resultado é um quadro de dados organizado com três colunas, onde cada coluna representa uma variável e cada obeservação é salva em sua própria linha.

3.5 Função spread()

A segunda função principal do tidyr é spread(). Esta função pega dados que estão em um formato de valor-chave e retorna um formato retangular de célula organizada. Isso pode parecer confuso, então vamos aplicar esta função no quadro de dados de poluição para ilustrar sua funcionalidade:

Como você pode ver, spread() reestrutura o quadro de dados removendo linhas redundantes sem perder nenhuma informação.

Duas outras funções úteis são unite() e separate(). Para mostrar seu uso, vamos olhar o quandro de dados storms novamente:

##     storm wind pressure       date
## 1 Alberto  110     1007 2000-08-03
## 2    Alex   45     1009 1998-07-27
## 3 Allison   65     1005 1995-06-03
## 4     Ana   40     1013 1997-06-30
## 5  Arlene   50     1010 1999-06-11
## 6  Arthur   45     1010 1996-06-17

separate() pode ser usado para separar uma coluna em várias outras colunas usando um separador. Digamos, por exemplo, que, em vez do formato de data AAAA-MM-DD que esta no storms e em uma única coluna, desejemos três colunas separadas: uma com o ano, uma com o mês e outra com o dia. Isso pode ser alcançado com o seguinte comando:

unite() faz exatamente o oposto. Ele une várias colunas em uma única coluna. Isso pode ser demonstrado usando nosso novo quadro de dados:

## # A tibble: 6 x 4
##   storm    wind pressure date      
##   <chr>   <int>    <int> <chr>     
## 1 Alberto   110     1007 2000-08-03
## 2 Alex       45     1009 1998-07-27
## 3 Allison    65     1005 1995-06-03
## 4 Ana        40     1013 1997-06-30
## 5 Arlene     50     1010 1999-06-11
## 6 Arthur     45     1010 1996-06-17

3.5.1 Exercícios

  • 1.Qual a diferença entre uma matriz e um data frame no R?
  • 2.Os data frames podem ser indexados com a mesma sintaxe utilizada para matrizes?
  • 3.Qual função básica que utilizamos para verificar a estrutura dos dados de um data frame?

3.5.2 Exercícios

    1. Reescreva a expressão abaixo utilizando o %>%.

round(mean(sum(1:10)/3), digits = 1)

Dica: utilize a função magrittr::divide_by(). Veja o help da função para mais informações.

    1. Reescreva o código abaixo utilizando o %>%.

x <- rnorm(100)
x.pos <- x[x>0]
media <- mean(x.pos)
saida <- round(media, 1)

    1. Sem rodar, diga qual a saída do código abaixo. Consulte o help das funções caso precise.

2 %>%
add(2) %>%
c(6, NA) %>%
mean(na.rm = T) %>%
equals(5)