9.3 Restruturação de dados retangulares

Até 80% do tempo da análise dados é dedicada ao processo de limpeza e preparação dos dados (Dasu and Johnson 2003, New York Times 2014/08/18).

9.3.1 Dados arrumados

O conceito "dados arrumados" foi estabelecido por H. Wickham (2014) e representa uma forma padronizada de conectar a estrutura (formato) de um conjunto de dados a sua semântica (significado).

Dados bem estruturados servem para:

  • fornecer dados propícios para o processamento e análise de dados por softwares;

  • revelar informações e facilitar a percepção de padrões

Dados no "formato arrumado" atendem as seguintes regras para dados retangulares:

  1. cada variável está em uma coluna

  2. cada observação corresponde a uma linha

  3. cada valor corresponde a uma célula

  4. cada tipo de unidade observacional deve compor uma tabela

Como sinônimo de observações você pode encontrar os termos: registros, casos, exemplos, instâncias ou amostras dependendo da área de aplicação.

Estrutura de dados padronizados

Estrutura de dados padronizados

Um exemplo de dados no formato arrumado é o tibble prec_anual_tbl mostrado abaixo:

site ano prec intensidade
A001 2000 1800 4.928131
A001 2001 1400 3.832991
A002 2000 1750 4.791239
A002 2001 1470 4.024641
A002 2002 1630 4.462697
A003 2004 1300 3.559206
A803 2005 1950 5.338809
A803 2006 1100 3.011636

Os dados acima tem duas variáveis: precipitação (prec) e intensidade da precipitação (intensidade). As unidades observacionais são as colunas site e ano. A primeira unidade observacional informa o ponto de amostragem espacial e a segunda o ponto de amostragem temporal.

Uma variável contém todos valores que medem um mesmo atributo ao longo das unidades observacionais. Uma observação contém todos valores medidos na mesma unidade observacional ao longo dos atributos. Cada valor (número ou caractere) pertence a uma variável e uma observação.

Exemplo de diferentes tipos de unidades observacionais são a tabela com a séries temporais dos elementos meteorológicos (exemplo acima) e a tabela com os metadados das estações de superfície que contém atributos das estações meteorológicas (site no exemplo acima), tais como: longitude, latitude, altitude, nome, município, estado e etc.

A estrutura de dados "arrumados" parece óbvia, mas na prática, dados neste formatos são raros de serem encontrados. As razões para isso incluem:

  • quem projeta a coleta e o registro de dados nem sempre é aquele que gasta tempo trabalhando sobre os dados;

  • a organização dos dados busca tornar o registro de dados o mais fácil possível;

Consequente, dados reais sempre precisarão ser arrumados. O primeiro passo é identificação das variáveis e das observações. O passo seguinte é resolver os seguintes problemas mais comuns (H. Wickham and Grolemund 2017):

  • uma variável deve ser distribuída ao longo das colunas

  • uma observação deve ser distribuída ao longo das linhas

Essas duas operações são realizadas com as principais funções do pacote tidyr:

  • gather(), que pode ser traduzida como reunir (nas linhas);

  • spread() que pode ser traduzida como espalhar (nas colunas)

9.3.2 Formatos de dados mais comuns

O pacote tidyr é a extensão do que fornece funcionalidades para reestruturar os dados entre diferentes formatos.

Os principais formatos de dados são:

  • dados longos, são tabelas com mais valores ao longo das linhas; geralmente mistura variáveis com observações;

  • dados amplos, são tabelas com valores mais distribuídos nas colunas, geralmente contém pelo menos uma unidade observacional misturada com variáveis;

9.3.2.1 Formato de dados longo

Para exemplificar o formato de dados longo vamos partir dos "dados arrumados" do exemplo, prec_anual_tbl. Primeiro vamos renomear a variável int prec para intensidade para seguir um o padrão de nome das variáveis mais conveniente para o seu processamento no R.

prec_anual_tbl <- rename(
  prec_anual_tbl,
  "intensidade" = `int prec`
) 
prec_anual_tbl
#> # A tibble: 8 x 4
#>   site    ano  prec intensidade
#>   <chr> <dbl> <dbl>       <dbl>
#> 1 A001   2000  1800        4.93
#> 2 A001   2001  1400        3.83
#> 3 A002   2000  1750        4.79
#> 4 A002   2001  1470        4.02
#> 5 A002   2002  1630        4.46
#> 6 A003   2004  1300        3.56
#> 7 A803   2005  1950        5.34
#> 8 A803   2006  1100        3.01

Vamos usar a função tidyr::gather() para reestruturar os dados prec_anual_tbl em uma nova tabela de dados que chamaremos prec_anual_long.

Na nova tabela, manteremos as colunas site, ano e teremos dois novos pares de variáveis: variavel e valor. Na coluna variavel será distribuído o nome das variáveis prec e intensidade. A coluna valorreunirá os valores das variáveis prec e intensidade.

prec_anual_long <- gather(
  data = prec_anual_tbl,
  key = variavel,
  value = medida,
  prec, intensidade
)
prec_anual_long
#> # A tibble: 16 x 4
#>    site    ano variavel     medida
#>    <chr> <dbl> <chr>         <dbl>
#>  1 A001   2000 prec        1800   
#>  2 A001   2001 prec        1400   
#>  3 A002   2000 prec        1750   
#>  4 A002   2001 prec        1470   
#>  5 A002   2002 prec        1630   
#>  6 A003   2004 prec        1300   
#>  7 A803   2005 prec        1950   
#>  8 A803   2006 prec        1100   
#>  9 A001   2000 intensidade    4.93
#> 10 A001   2001 intensidade    3.83
#> 11 A002   2000 intensidade    4.79
#> 12 A002   2001 intensidade    4.02
#> 13 A002   2002 intensidade    4.46
#> 14 A003   2004 intensidade    3.56
#> 15 A803   2005 intensidade    5.34
#> 16 A803   2006 intensidade    3.01

O código acima demonstra os principais argumentos requeridos pela função gather:

  • data = prec_anual_tbl, o data frame ou tibble que será reestruturado;

  • key = variavel, nome que nós escolhemos para dar à nova coluna que distribuirá os nomes das variáveis dos dados de entrada.

  • value = medida, nome que nós escolhemos para dar à nova coluna que reunirá os valores das variáveis dos dados de entrada;

  • ..., lista com o nome das variáveis, no código acima corresponde à prec, intensidade;

As demais colunas dos dados (site e ano) serão mantidas inalteradas e seus valores serão repetidos quando necessário.

Como em outras funções dos pacotes do tidyverse você perceberá que os argumentos não são especificados como caracteres e sim como nomes (ou seja o nome da variável sem aspas), como aqueles usados quando definimos variáveis (p.ex.: nome_var <- 10). Os argumentos key e value podem ser especificados à gosto do usuário e não precisam ter relação com os dados existentes.

Se nós desejássemos que todas colunas do data frame fossem reunidas em uma nova coluna atributo e os seus valores em uma nova coluna valor, isso poderia ser feito simplesmente sem especificar variáveis de interesse (prec, intensidade) no trecho de código anterior. A tabela de dados resultante conterá todos os 32 pares de valores, formados pelas 4 colunas por 8 linhas, dos dados originais:

prec_anual_longo <- gather(
  prec_anual_tbl, 
  key = atributo,
  value = valor
)
prec_anual_longo
#> # A tibble: 32 x 2
#>    atributo valor
#>    <chr>    <chr>
#>  1 site     A001 
#>  2 site     A001 
#>  3 site     A002 
#>  4 site     A002 
#>  5 site     A002 
#>  6 site     A003 
#>  7 site     A803 
#>  8 site     A803 
#>  9 ano      2000 
#> 10 ano      2001 
#> # ... with 22 more rows

Se não forem especificados nomes para os argumentos key e value na chamada da função tidyr::gather(), serão atribuídos os valores default: key e value.

gather(prec_anual_tbl)
#> # A tibble: 32 x 2
#>    key   value
#>    <chr> <chr>
#>  1 site  A001 
#>  2 site  A001 
#>  3 site  A002 
#>  4 site  A002 
#>  5 site  A002 
#>  6 site  A003 
#>  7 site  A803 
#>  8 site  A803 
#>  9 ano   2000 
#> 10 ano   2001 
#> # ... with 22 more rows

9.3.2.2 Formato de dados amplo

Utilizando os dados meteo_long, vamos reestruturá-lo no formato amplo para demostrar a funcionalidade da função tidyr::spread(). Esta função é complementar à tidyr::gather().

prec_anual_long
#> # A tibble: 16 x 4
#>    site    ano variavel     medida
#>    <chr> <dbl> <chr>         <dbl>
#>  1 A001   2000 prec        1800   
#>  2 A001   2001 prec        1400   
#>  3 A002   2000 prec        1750   
#>  4 A002   2001 prec        1470   
#>  5 A002   2002 prec        1630   
#>  6 A003   2004 prec        1300   
#>  7 A803   2005 prec        1950   
#>  8 A803   2006 prec        1100   
#>  9 A001   2000 intensidade    4.93
#> 10 A001   2001 intensidade    3.83
#> 11 A002   2000 intensidade    4.79
#> 12 A002   2001 intensidade    4.02
#> 13 A002   2002 intensidade    4.46
#> 14 A003   2004 intensidade    3.56
#> 15 A803   2005 intensidade    5.34
#> 16 A803   2006 intensidade    3.01

Nosso objetivo é então gerar uma nova tabela de dados reestruturada, de forma que os nomes das variáveis (contidos na coluna variavel) sejam distribuídos em duas colunas. Estas colunas receberão os nomes prec e intensidade e serão preenchidas com os valores armazenados na coluna medida. Para fazer isso usamos o seguinte código:

prec_anual_amplo <- spread(
  data = prec_anual_long,
  key = variavel,
  value = medida
)
prec_anual_amplo
#> # A tibble: 8 x 4
#>   site    ano intensidade  prec
#>   <chr> <dbl>       <dbl> <dbl>
#> 1 A001   2000        4.93  1800
#> 2 A001   2001        3.83  1400
#> 3 A002   2000        4.79  1750
#> 4 A002   2001        4.02  1470
#> 5 A002   2002        4.46  1630
#> 6 A003   2004        3.56  1300
#> 7 A803   2005        5.34  1950
#> 8 A803   2006        3.01  1100

Esta operação serviu para colocar os dados originais (prec_anual_long) no formato "arrumado" (prec_anual_amplo).

9.3.3 Funções adicionais do tidyr

Você pode unir duas colunas inserindo um separador entre elas com a função tidyr::unite():

(prec_anual_long_u <- unite(
  prec_anual_long,
  col = site_ano,
  site, ano,
  sep = "_"
))
#> # A tibble: 16 x 3
#>    site_ano  variavel     medida
#>    <chr>     <chr>         <dbl>
#>  1 A001_2000 prec        1800   
#>  2 A001_2001 prec        1400   
#>  3 A002_2000 prec        1750   
#>  4 A002_2001 prec        1470   
#>  5 A002_2002 prec        1630   
#>  6 A003_2004 prec        1300   
#>  7 A803_2005 prec        1950   
#>  8 A803_2006 prec        1100   
#>  9 A001_2000 intensidade    4.93
#> 10 A001_2001 intensidade    3.83
#> 11 A002_2000 intensidade    4.79
#> 12 A002_2001 intensidade    4.02
#> 13 A002_2002 intensidade    4.46
#> 14 A003_2004 intensidade    3.56
#> 15 A803_2005 intensidade    5.34
#> 16 A803_2006 intensidade    3.01

Se ao contrário, você quer separar uma coluna em duas variáveis, utilize a função tidyr::separate():

separate(
  prec_anual_long_u,
  col = site_ano,
  sep = "_",
  into = c("site", "ano")
)
#> # A tibble: 16 x 4
#>    site  ano   variavel     medida
#>    <chr> <chr> <chr>         <dbl>
#>  1 A001  2000  prec        1800   
#>  2 A001  2001  prec        1400   
#>  3 A002  2000  prec        1750   
#>  4 A002  2001  prec        1470   
#>  5 A002  2002  prec        1630   
#>  6 A003  2004  prec        1300   
#>  7 A803  2005  prec        1950   
#>  8 A803  2006  prec        1100   
#>  9 A001  2000  intensidade    4.93
#> 10 A001  2001  intensidade    3.83
#> 11 A002  2000  intensidade    4.79
#> 12 A002  2001  intensidade    4.02
#> 13 A002  2002  intensidade    4.46
#> 14 A003  2004  intensidade    3.56
#> 15 A803  2005  intensidade    5.34
#> 16 A803  2006  intensidade    3.01

Para completar valores das variáveis para unidades observacionais faltantes podemos utilizar a função tidyr::complete():

prec_anual
#>   site  ano prec
#> 1 A001 2000 1800
#> 2 A001 2001 1400
#> 3 A002 2000 1750
#> 4 A002 2001 1470
#> 5 A002 2002 1630
#> 6 A003 2004 1300
#> 7 A803 2005 1950
#> 8 A803 2006 1100
prec_anual_comp <- complete(
  prec_anual,
  site, ano
)
prec_anual_comp
#> # A tibble: 24 x 3
#>    site    ano  prec
#>    <fct> <dbl> <dbl>
#>  1 A001   2000  1800
#>  2 A001   2001  1400
#>  3 A001   2002    NA
#>  4 A001   2004    NA
#>  5 A001   2005    NA
#>  6 A001   2006    NA
#>  7 A002   2000  1750
#>  8 A002   2001  1470
#>  9 A002   2002  1630
#> 10 A002   2004    NA
#> # ... with 14 more rows

References

Dasu, Tamraparni, and Theodore Johnson. 2003. “Data Quality.” In Exploratory Data Mining and Data Cleaning, edited by Walter A. Shewhart and Samuel S. Wilks, 99–137. Wiley-Blackwell. doi:10.1002/0471448354.ch4.

Wickham, H. 2014. “Tidy Data.” Journal of Statistical Software, Articles 59 (10): 1–23. doi:10.18637/jss.v059.i10.

Wickham, H., and G. Grolemund. 2017. R for Data Science. O’Reilly Media. http://r4ds.had.co.nz/.