Em muitos momentos você vai precisar converter dados do formato long ("long-form" — o que isso significa ficará claro adiante) para o formato wide e vice-versa. Na prática, os dados chegam em todo tipo de formato, mas a maioria das funções do R foi pensada para um formato específico.
Por exemplo, lme4::lmer() para modelos lineares mistos e ggplot2::ggplot() para visualização foram projetadas para dados em long-form. Já outras funções esperam dados em wide-form, como mosaicplot(). Isso significa que você precisa converter o formato para analisar ou visualizar, a menos que os dados já tenham sido processados e estejam no formato certo.
Existem várias opções no R para conversão de formato, mas para quem está começando pode ser bem confuso.
Este tutorial mostra a mecânica de converter dados entre long-form e wide-form. Você vai ver:
O que é o formato long.
Depois, o que é o formato wide.
Um resumo das diferenças entre os formatos long e wide;
Os passos necessários para ir de um formato ao outro.
Por fim, como fazer tudo isso no R. Você vai aprender a ir de long para wide com as funções melt() e dcast().
Os dados
Tabela 01
name
gender
year2011
year2012
year2013
year2014
year2015
Jackson Smith
M
74.69
84.99
91.73
105.11
111.04
Sophia Johnson
F
NA
NA
NA
NA
75.89
Emma Williams
F
NA
NA
75.74
86.50
91.50
Aiden Jones
M
NA
NA
NA
71.89
81.42
Liam Brown
M
88.24
96.91
101.85
108.13
112.45
Lucas Davis
M
70.60
83.78
94.17
100.03
106.35
Olivia Miller
F
64.78
80.76
87.30
97.13
103.80
Ava Wilson
F
88.77
96.45
104.72
112.84
NA
Esta tabela mostra a altura de bebês em uma pequena região. As alturas foram medidas de 2011 a 2015. Como você já deve saber, NA significa "Not Available" (não disponível). Pela posição dos NAs, dá para inferir a idade dos bebês, mas a idade exata não está disponível na tabela. Ela parece bem organizada, mas para quem quer estudar crescimento infantil existe um problema: o que importa não é o momento absoluto da medição, e sim a idade do bebê no momento da medição. Dá para inserir essa informação na tabela? Abaixo está uma forma:
Tabela 02
name
gender
age0
age1
age2
age3
age4
age5
age6
Jackson Smith
M
NA
76.69
84.91
97.06
105.73
107.32
NA
Sophia Johnson
F
NA
76.05
NA
NA
NA
NA
NA
Emma Williams
F
72.65
82.46
91.76
NA
NA
NA
NA
Aiden Jones
M
69.76
79.89
NA
NA
NA
NA
NA
Liam Brown
M
NA
NA
85.34
93.22
105.78
105.84
114.82
Lucas Davis
M
71.59
84.87
92.10
100.73
104.21
NA
NA
Olivia Miller
F
62.74
81.39
92.02
98.32
106.44
NA
NA
Ava Wilson
F
NA
NA
88.39
100.67
107.58
111.52
NA
O número de NAs aumentou. ## Dados em wide-form Mas como você faria para indicar quantos meses o bebê tinha? Seria algo assim:
Tabela 03
name
gender
m4
m6
m7
m10
m12
...
m55
m60
m65
m72
Jackson Smith
M
NA
NA
NA
NA
76.69
...
NA
107.32
NA
NA
Sophia Johnson
F
NA
NA
NA
NA
76.05
...
NA
NA
NA
NA
Emma Williams
F
NA
NA
NA
72.65
NA
...
NA
NA
NA
NA
Aiden Jones
M
NA
69.76
NA
NA
NA
...
NA
NA
NA
NA
Liam Brown
M
NA
NA
NA
NA
NA
...
NA
105.84
NA
114.82
Lucas Davis
M
NA
NA
71.59
NA
NA
...
104.21
NA
NA
NA
Olivia Miller
F
62.74
NA
NA
NA
NA
...
NA
NA
NA
NA
Ava Wilson
F
NA
NA
NA
NA
NA
...
NA
NA
111.52
NA
Há inúmeros NAs na tabela acima. Se os bebês diferem nos momentos relativos das medições, o formato wide pode desperdiçar muito espaço. Outra opção seria incluir as idades dos bebês referentes a 2015, mas isso só funciona quando os tempos absolutos de medição são os mesmos. Se as datas variam por meses e você quer idades em meses, não funciona. Neste caso, o formato long é uma alternativa melhor. ## Dados em long-form Enquanto no wide-form todas as medições de um bebê ficam em uma linha, no long-form cada linha traz uma única medição de um bebê. A forma mais simples seria exibir o nome da criança, o momento da medição e a medição (altura) em cada linha. É exatamente o que esta tabela mostra:
Tabela 04
name
gender
month
height
Olivia Miller
F
4
62.74
Aiden Jones
M
6
69.76
Lucas Davis
M
7
71.59
Emma Williams
F
10
72.65
Jackson Smith
M
12
76.69
...
...
...
...
Liam Brown
M
72
114.82
Se você ordenar por nome, terá algo como a tabela abaixo. E ela ocupa bem menos espaço que a Tabela 3!
Tabela 05
name
gender
month
height
Jackson Smith
M
12
76.69
Jackson Smith
M
24
84.91
Jackson Smith
M
36
97.06
Jackson Smith
M
48
105.73
Jackson Smith
M
60
107.32
Sophia Johnson
F
12
76.05
Emma Williams
F
10
72.65
...
...
...
...
Ava Wilson
F
65
111.52
Long versus wide
Repare de novo nas diferenças fundamentais entre wide-form e long-form: uma diferença simples é que o wide-form mostra várias medições de um indivíduo em uma linha, e os nomes das colunas indicam o que são essas medições.
Esta tabela mostra as alturas de Liam Brown em 2011-2015 em uma única linha:
Tabela 06
name
gender
year2011
year2012
year2013
year2014
year2015
Liam Brown
M
88.24
96.91
101.85
108.13
112.45
No long-form, as alturas de Liam Brown aparecem em uma coluna:
Tabela 07
name
gender
_
Liam Brown
M
85.34
Liam Brown
M
93.22
Liam Brown
M
105.78
Liam Brown
M
105.84
Liam Brown
M
114.82
Assim, você não sabe o que essas medições representam. Se anotar o nome da coluna, ficaria assim:
Tabela 08
name
gender
year2011, 2012, 2013, 2014, 2015
Liam Brown
M
85.34
Liam Brown
M
93.22
Liam Brown
M
105.78
Liam Brown
M
105.84
Liam Brown
M
114.82
Mas isso também tem um problema. As alturas de Sophia Johnson não foram medidas de 2011 a 2014. Então, como você vê abaixo, o nome da coluna não pode ser definido com facilidade:
Tabela 09
name
gender
?
Liam Brown
M
85.34
Liam Brown
M
93.22
Liam Brown
M
105.78
Liam Brown
M
105.84
Liam Brown
M
114.82
Sophia Johnson
F
76.05
De wide-form para long-form
Converter de wide para long pode ser pensado como um processo em etapas. Antes de transformar várias medições de uma linha em uma coluna, você pode reestruturar a tabela para que haja apenas uma medição por linha. Vamos fazer isso com esta tabela:
Tabela 10
name
gender
age0
age1
age2
age3
age4
age5
age6
Emma Williams
F
72.65
82.46
91.76
NA
NA
NA
NA
Aiden Jones
M
69.76
79.89
NA
NA
NA
NA
NA
O resultado fica assim:
Tabela 11
name
gender
age0
age1
age2
age3
age4
age5
age6
Emma Williams
F
72.65
NA
NA
NA
NA
Emma Williams
F
82.46
NA
Emma Williams
F
91.76
Aiden Jones
M
69.76
NA
NA
NA
NA
NA
Aiden Jones
M
79.89
Antes de juntar essas medições espalhadas pelas colunas em uma única coluna, você precisa criar uma coluna adicional dizendo o que é a medição, como abaixo:
Tabela 12
name
gender
measure
age0
age1
age2
age3
age4
age5
age6
Emma Williams
F
age0
72.65
NA
NA
NA
NA
Emma Williams
F
age1
82.46
NA
Emma Williams
F
age2
91.76
Aiden Jones
M
age0
69.76
NA
NA
NA
NA
NA
Aiden Jones
M
age1
79.89
O nome dessa coluna geralmente é "measure" ou "key". Note na tabela acima que aparecem "age0", "age1", "age2", "age3", "age4", "age5" tanto nos nomes das colunas quanto em uma coluna. Se você omitir os nomes das colunas, a tabela fica assim:
Tabela 13
name
gender
measure
_
__
___
____
_____
______
_______
Emma Williams
F
age0
72.65
NA
NA
NA
NA
Emma Williams
F
age1
82.46
Emma Williams
F
age2
91.76
Aiden Jones
M
age0
69.76
NA
NA
NA
NA
NA
Aiden Jones
M
age1
79.89
Como agora há apenas uma medição por linha, você pode juntá-las em uma coluna, resultando em:
Tabela 14
name
gender
measure
Emma Williams
F
age0
72.65
Emma Williams
F
age1
82.46
Emma Williams
F
age2
91.76
Aiden Jones
M
age0
69.76
Aiden Jones
M
age1
79.89
Vamos dar um nome para a nova coluna de medições. Normalmente ela se chama "value":
Tabela 15
name
gender
measure
value
Emma Williams
F
age0
72.65
Emma Williams
F
age1
82.46
Emma Williams
F
age2
91.76
Aiden Jones
M
age0
69.76
Aiden Jones
M
age1
79.89
Observe a tabela acima. Percebeu que "age" se repete? Você pode remover o prefixo repetido, chegando a:
Tabela 16
name
gender
age
value
Emma Williams
F
0
72.65
Emma Williams
F
1
82.46
Emma Williams
F
2
91.76
Aiden Jones
M
0
69.76
Aiden Jones
M
1
79.89
Age, que se repetia em todas as linhas, agora é um nome de coluna. O nome value pode ser mais específico. Vamos trocá-lo por height, que comunica melhor. Veja o resultado:
Tabela 17
name
gender
age
height
Emma Williams
F
0
72.65
Emma Williams
F
1
82.46
Emma Williams
F
2
91.76
Aiden Jones
M
0
69.76
Aiden Jones
M
1
79.89
Compare a Tabela 15 com a Tabela 17. value pode significar qualquer coisa, enquanto height tem significado específico: altura. Já value na Tabela 15 poderia ser altura, peso, velocidade ou cor. Outra alternativa seria esta:
Tabela 18
name
gender
measure
value
Emma Williams
F
height.age0
72.65
Emma Williams
F
height.age1
82.46
Emma Williams
F
height.age2
91.76
Aiden Jones
M
height.age0
69.76
Aiden Jones
M
height.age1
79.89
Considere agora que as medições são diversas. Se forem altura, peso e IMC, teríamos algo como a tabela abaixo. Mas aí a coluna value reúne valores em escalas diferentes, o que pode confundir a leitura. Nesta tabela, altura está em centímetros e peso em quilogramas:
Tabela 19
name
gender
measure
value
Emma Williams
F
height
72.65
Emma Williams
F
weight
8.22
Emma Williams
F
BMI
22.60
Aiden Jones
M
height
69.76
Aiden Jones
M
weight
8.51
Portanto, ao converter de wide para long, você precisa decidir quais valores serão reunidos em uma coluna. Depois, definir o nome dessa coluna.
Resumindo: para converter de wide para long você precisa decidir quais colunas serão combinadas em uma única coluna. Ao fazer isso, várias colunas viram uma só, então é necessário um nome para ela, como mostram as próximas tabelas:
Tabela 20
id1
id2
age0
age1
age2
Emma Williams
F
NA
82.46
91.76
Aiden Jones
M
69.76
79.89
NA
Emma Williams
F
NA
82.46
91.76
Tabela 21
id1
id2
age0
age1
age2
Emma Williams
F
NA
Emma Williams
F
82.46
Emma Williams
F
91.76
Aiden Jones
M
69.76
Aiden Jones
M
79.89
Aiden Jones
M
NA
Emma Williams
F
NA
Emma Williams
F
82.46
Emma Williams
F
91.76
Tabela 22
id1
id2
age_
age0
age1
age2
Emma Williams
F
age0
NA
Emma Williams
F
age1
82.46
Emma Williams
F
age2
91.76
Aiden Jones
M
age0
69.76
Aiden Jones
M
age1
79.89
Aiden Jones
M
age2
NA
Emma Williams
F
age0
NA
Emma Williams
F
age1
82.46
Emma Williams
F
age2
91.76
Tabela 23
id1
id2
age_
Emma Williams
F
age0
NA
Emma Williams
F
age1
82.46
Emma Williams
F
age2
91.76
Aiden Jones
M
age0
69.76
Aiden Jones
M
age1
79.89
Aiden Jones
M
age2
NA
Emma Williams
F
age0
NA
Emma Williams
F
age1
82.46
Emma Williams
F
age2
91.76
Tabela 24
id1
id2
key
value
Emma Williams
F
age0
NA
Emma Williams
F
age1
82.46
Emma Williams
F
age2
91.76
Aiden Jones
M
age0
69.76
Aiden Jones
M
age1
79.89
Aiden Jones
M
age2
NA
Emma Williams
F
age0
NA
Emma Williams
F
age1
82.46
Emma Williams
F
age2
91.76
Tabela 25
id1
id2
key
value
Emma Williams
F
age1
82.46
Emma Williams
F
age2
91.76
Aiden Jones
M
age0
69.76
Aiden Jones
M
age1
79.89
Emma Williams
F
age1
82.46
Emma Williams
F
age2
91.76
Observe as colunas id1 e id2 na tabela acima. id2 não identifica um indivíduo; é um atributo (gênero) do indivíduo. Em outras palavras, pode ser tratado como uma medição. Portanto, você pode converter para um formato ainda mais long. O formato mais "longo" possível tem três colunas: id, key e value.
Tabela 26
id
key
value
Emma Williams
gender
F
Emma Williams
age1
82.46
Emma Williams
age2
91.76
Aiden Jones
gender
F
Aiden Jones
age0
69.76
Aiden Jones
age1
79.89
Emma Williams
gender
F
Emma Williams
age1
82.46
Emma Williams
age2
91.76
A tabela acima mostra o formato mais longo possível da Tabela 25. Porém, pessoas diferentes podem ter o mesmo nome.
Nesse caso, o long-form pode gerar ambiguidade, já que id não identifica unicamente a pessoa. Você pode adicionar um número após o nome para diferenciar (por exemplo, com make.unique() no R), mas não há como distinguir um nome que originalmente já tinha número. Pense em alguém que realmente se chame "John.2"!
A saída óbvia é atribuir um identificador numérico distinto para cada pessoa. Nesse cenário, o nome passa a ser mais uma medição.
A próxima tabela mostra que até os nomes entram como medições. Em certo sentido, este é o formato verdadeiramente mais longo.
Tabela 27
id
key
value
1
name
Emma Williams
1
gender
F
1
age1
82.46
1
age2
91.76
2
name
Aiden Jones
2
gender
F
2
age0
69.76
2
age1
79.89
3
name
Emma Williams
3
gender
F
3
age1
82.46
3
age2
91.76
O formato mais longo é o mais fácil de transformar de volta em wide-form. Se você reverter o processo mostrado nas Tabelas 20 a 25, chega ao formato wide. As tabelas a seguir mostram esse processo:
Tabela 28. As medições na coluna key viram nomes de colunas
id
key
name
gender
age0
age1
age2
1
name
Emma Williams
1
gender
F
1
age1
82.46
1
age2
91.76
2
name
Aiden Jones
2
gender
F
2
age0
69.76
2
age1
79.89
3
name
Emma Williams
3
gender
F
3
age1
82.46
3
age2
91.76
Tabela 29. A coluna key pode ser removida
id
name
gender
age0
age1
age2
1
Emma Williams
1
F
1
82.46
1
91.76
2
Aiden Jones
2
F
2
69.76
2
79.89
3
Emma Williams
3
F
3
82.46
3
91.76
Tabela 30. O mesmo id pode ser reunido em uma linha
id
name
gender
age0
age1
age2
1
Emma Williams
F
82.46
91.76
1
1
1
2
Aiden Jones
F
69.76
79.89
2
2
2
3
Emma Williams
F
82.46
91.76
3
3
3
Tabela 31. Exclua linhas sem medições
id
name
gender
age0
age1
age2
1
Emma Williams
F
82.46
91.76
2
Aiden Jones
F
69.76
79.89
3
Emma Williams
F
82.46
91.76
O ponto-chave ao converter de wide para long é decidir quais colunas serão reunidas em uma só.
Mas não precisa ser apenas uma. Você pode usar duas colunas, se necessário, como na tabela abaixo:
Tabela 32
name
gender
h2011
h2012
w2011
w2012
Jackson Smith
M
74.69
84.99
9.60
12.0
Olivia Miller
F
NA
80.76
7.15
10.7
Ava Wilson
F
88.77
96.45
NA
15.0
Você consegue levá-la para o long-form?
As colunas h2011, h2012, w2011, w2012 significam alturas e pesos em 2011 e 2012. height e weight estão em escalas diferentes — cm e kg. Você pode usar uma coluna só para ambos ou duas colunas, como nesta tabela:
Tabela 33
name
gender
year
height
weight
Jackson Smith
M
2011
74.69
9.60
Jackson Smith
M
2012
84.99
12.00
Olivia Miller
F
2011
NA
80.76
Olivia Miller
F
2012
7.15
10.70
Ava Wilson
F
2011
88.77
96.45
Ava Wilson
F
2012
NA
15.00
Este é long-form ou wide-form?
De long para wide no R
Vamos fazer a conversão entre long e wide no R. Existem várias funções e pacotes para isso.
Tabela 34
func
package
to_long_form
to_wide_form
stack/unstack
utils
stack
unstack
reshape
stats
reshape(direction="long", ...)
reshape(direction="wide", ...)
melt/dcast
reshape2
melt
dcast
gather/spread
tidyr
gather
spread
Aqui, vamos ver como usar as funções melt() e dcast() do pacote reshape2. O motivo é que stack() e unstack() são funções básicas e normalmente exigem pós-processamento. Já gather() e spread() do tidyr também são muito populares, mas não serão abordadas neste tutorial.
Outra função possível é reshape(), do pacote stats. Não confunda com o pacote reshape! Esse pacote, junto com o reshape2, foi criado para quem tinha dificuldades com reshape(). Além disso, reshape() parece assumir dados longitudinais (medições repetidas ao longo do tempo).
Vamos converter os dados da Tabela 35 para long-form. Suponha que a tabela abaixo esteja em um data.frame chamado dat.
## name gender year2011 year2012 year2013
## 1 Jackson Smith M74.6984.9991.73
## 2 Emma Williams FNANA75.74
## 3 Liam Brown M88.24NA101.83
## 4 Ava Wilson F88.7796.45NATecnologia
A pergunta é: "quais colunas combinar em uma só?".
Neste caso, year2011, year2012, year2013. Ao usar melt(), liste essas colunas em measure.vars:
melt(babies, measure.vars =c("year2011","year2012","year2013"))
## name gender variable value
## 1 Jackson Smith M year2011 74.69
## 2 Emma Williams F year2011 NA
## 3 Liam Brown M year2011 88.24
## 4 Ava Wilson F year2011 88.77
## 5 Jackson Smith M year2012 84.99
## 6 Emma Williams F year2012 NA
## 7 Liam Brown M year2012 NA
## 8 Ava Wilson F year2012 96.45
## 9 Jackson Smith M year2013 91.73
## 10 Emma Williams F year2013 75.74
## 11 Liam Brown M year2013 101.83
## 12 Ava Wilson F year2013 NATecnologia
year2011, year2012, year2013 estão nas colunas 3, 4 e 5, então você pode usar:
melt(babies, measure.vars =3:5)
## name gender variable value
## 1 Jackson Smith M year2011 74.69
## 2 Emma Williams F year2011 NA
## 3 Liam Brown M year2011 88.24
## 4 Ava Wilson F year2011 88.77
## 5 Jackson Smith M year2012 84.99
## 6 Emma Williams F year2012 NA
## 7 Liam Brown M year2012 NA
## 8 Ava Wilson F year2012 96.45
## 9 Jackson Smith M year2013 91.73
## 10 Emma Williams F year2013 75.74
## 11 Liam Brown M year2013 101.83
## 12 Ava Wilson F year2013 NATecnologia
O resultado é o mostrado acima. Note os nomes das colunas variable e value. As Tabelas 23 e 24 mostraram que novos nomes de colunas são necessários. A função melt() usa por padrão variable e value. Você pode sobrescrever com variable.name= e value.name=. Veja:
melt(babies, measure.vars=3:5, variable.name="year", value.name="height")
## name gender year height
## 1 Jackson Smith M year2011 74.69
## 2 Emma Williams F year2011 NA
## 3 Liam Brown M year2011 88.24
## 4 Ava Wilson F year2011 88.77
## 5 Jackson Smith M year2012 84.99
## 6 Emma Williams F year2012 NA
## 7 Liam Brown M year2012 NA
## 8 Ava Wilson F year2012 96.45
## 9 Jackson Smith M year2013 91.73
## 10 Emma Williams F year2013 75.74
## 11 Liam Brown M year2013 101.83
## 12 Ava Wilson F year2013 NATecnologia
Nas definições acima, especificamos as medições. Em outros cenários, as colunas de identificação (id) podem indiretamente especificar o restante. Assim, você pode escolher colunas de id em vez de medições.
Os dois comandos abaixo produzem o mesmo resultado. O primeiro escolhe as colunas de id; o segundo, as colunas a serem reunidas:
melt(babies, id.vars=c("name","gender"))melt(babies, measure.vars =c("year2011","year2012","year2013"))
## name gender variable value
## 1 Jackson Smith M year2011 74.69
## 2 Emma Williams F year2011 NA
## 3 Liam Brown M year2011 88.24
## 4 Ava Wilson F year2011 88.77
## 5 Jackson Smith M year2012 84.99
## 6 Emma Williams F year2012 NA
## 7 Liam Brown M year2012 NA
## 8 Ava Wilson F year2012 96.45
## 9 Jackson Smith M year2013 91.73
## 10 Emma Williams F year2013 75.74
## 11 Liam Brown M year2013 101.83
## 12 Ava Wilson F year2013 NATecnologia
Se você especificar tanto id.vars quanto measure.vars, as colunas que não estiverem em nenhuma dessas listas serão excluídas do resultado. Exemplo:
melt(babies, id.vars=c("name"), measure.vars=c("year2011","year2012"))
## name variable value
## 1 Jackson Smith year2011 74.69
## 2 Emma Williams year2011 NA
## 3 Liam Brown year2011 88.24
## 4 Ava Wilson year2011 88.77
## 5 Jackson Smith year2012 84.99
## 6 Emma Williams year2012 NA
## 7 Liam Brown year2012 NA
## 8 Ava Wilson year2012 96.45Tecnologia
Além disso, na.rm=T remove NAs:
melt(babies, id.vars=c("name"), measure.vars=c("year2011","year2012"), na.rm=T)
## name variable value
## 1 Jackson Smith year2011 74.69
## 3 Liam Brown year2011 88.24
## 4 Ava Wilson year2011 88.77
## 5 Jackson Smith year2012 84.99
## 8 Ava Wilson year2012 96.45Tecnologia
A função dcast() faz o inverso de melt(). id, variable e value são as colunas do formato mais longo. dcast(data, id ~ variable, value.var="value") leva do formato mais longo ao wide.
babiesLong <-melt(babies, id.vars=c("name"), measure.vars=c("year2011","year2012"), na.rm=T)
babiesLong
## name variable value
## 1 Jackson Smith year2011 74.69
## 3 Liam Brown year2011 88.24
## 4 Ava Wilson year2011 88.77
## 5 Jackson Smith year2012 84.99
## 8 Ava Wilson year2012 96.45Tecnologia
babiesLong tem name como id, variable como variável e value como valor. Logo, podemos usar dcast() para voltar ao wide:
dcast(babiesLong, name ~ variable, value.var="value")
## name year2011 year2012
## 1 Ava Wilson 88.7796.45
## 2 Jackson Smith 74.6984.99
## 3 Liam Brown 88.24NATecnologia
Conclusão
É isso! Neste tutorial, o foco foi entender a lógica e o processo de reshaping dos dados. Em geral, o long-form é preferido para análise, mas há exceções. A apresentação em wide-form pode economizar espaço quando faz sentido, porém, à medida que crescem os valores faltantes, vale mais a pena converter para long.
Na conversão de formatos, mantenha o foco no que são as medições. O lema do long-form é: uma medição por linha. No wide-form, várias medições por linha. Quando você reúne medições espalhadas por colunas em uma só coluna, os nomes originais dessas colunas precisam ser preservados em uma coluna adicional. Quando espalha os valores de uma coluna em várias colunas, é a partir da coluna variable que você define os nomes das novas colunas.
Depois que você entende o processo, usar funções como dcast() e melt() fica muito mais simples!
Descubra as complexidades dos modelos não lineares em comparação com os modelos lineares. Saiba mais sobre suas aplicações, limitações e como ajustá-las usando conjuntos de dados do mundo real.
Em muitos momentos você vai precisar converter dados do formato long ("long-form" — o que isso significa ficará claro adiante) para o formato wide e vice-versa. Na prática, os dados chegam em todo tipo de formato, mas a maioria das funções do R foi pensada para um formato específico.
Por exemplo,
lme4::lmer()para modelos lineares mistos eggplot2::ggplot()para visualização foram projetadas para dados em long-form. Já outras funções esperam dados em wide-form, comomosaicplot(). Isso significa que você precisa converter o formato para analisar ou visualizar, a menos que os dados já tenham sido processados e estejam no formato certo.Existem várias opções no R para conversão de formato, mas para quem está começando pode ser bem confuso.
Este tutorial mostra a mecânica de converter dados entre long-form e wide-form. Você vai ver:
melt()edcast().Os dados
Esta tabela mostra a altura de bebês em uma pequena região. As alturas foram medidas de 2011 a 2015. Como você já deve saber,
NAsignifica "Not Available" (não disponível). Pela posição dos NAs, dá para inferir a idade dos bebês, mas a idade exata não está disponível na tabela. Ela parece bem organizada, mas para quem quer estudar crescimento infantil existe um problema: o que importa não é o momento absoluto da medição, e sim a idade do bebê no momento da medição. Dá para inserir essa informação na tabela? Abaixo está uma forma:O número de
NAs aumentou. ## Dados em wide-form Mas como você faria para indicar quantos meses o bebê tinha? Seria algo assim:Há inúmeros
NAs na tabela acima. Se os bebês diferem nos momentos relativos das medições, o formato wide pode desperdiçar muito espaço. Outra opção seria incluir as idades dos bebês referentes a 2015, mas isso só funciona quando os tempos absolutos de medição são os mesmos. Se as datas variam por meses e você quer idades em meses, não funciona. Neste caso, o formato long é uma alternativa melhor. ## Dados em long-form Enquanto no wide-form todas as medições de um bebê ficam em uma linha, no long-form cada linha traz uma única medição de um bebê. A forma mais simples seria exibir o nome da criança, o momento da medição e a medição (altura) em cada linha. É exatamente o que esta tabela mostra:Se você ordenar por nome, terá algo como a tabela abaixo. E ela ocupa bem menos espaço que a Tabela 3!
Long versus wide
Repare de novo nas diferenças fundamentais entre wide-form e long-form: uma diferença simples é que o wide-form mostra várias medições de um indivíduo em uma linha, e os nomes das colunas indicam o que são essas medições.
Esta tabela mostra as alturas de Liam Brown em 2011-2015 em uma única linha:
No long-form, as alturas de Liam Brown aparecem em uma coluna:
Assim, você não sabe o que essas medições representam. Se anotar o nome da coluna, ficaria assim:
Mas isso também tem um problema. As alturas de Sophia Johnson não foram medidas de 2011 a 2014. Então, como você vê abaixo, o nome da coluna não pode ser definido com facilidade:
De wide-form para long-form
Converter de wide para long pode ser pensado como um processo em etapas. Antes de transformar várias medições de uma linha em uma coluna, você pode reestruturar a tabela para que haja apenas uma medição por linha. Vamos fazer isso com esta tabela:
O resultado fica assim:
Antes de juntar essas medições espalhadas pelas colunas em uma única coluna, você precisa criar uma coluna adicional dizendo o que é a medição, como abaixo:
O nome dessa coluna geralmente é
"measure"ou"key". Note na tabela acima que aparecem"age0","age1","age2","age3","age4","age5"tanto nos nomes das colunas quanto em uma coluna. Se você omitir os nomes das colunas, a tabela fica assim:Como agora há apenas uma medição por linha, você pode juntá-las em uma coluna, resultando em:
Vamos dar um nome para a nova coluna de medições. Normalmente ela se chama "value":
Observe a tabela acima. Percebeu que "age" se repete? Você pode remover o prefixo repetido, chegando a:
Age, que se repetia em todas as linhas, agora é um nome de coluna. O nomevaluepode ser mais específico. Vamos trocá-lo porheight, que comunica melhor. Veja o resultado:Compare a Tabela 15 com a Tabela 17.
valuepode significar qualquer coisa, enquantoheighttem significado específico: altura. Jávaluena Tabela 15 poderia ser altura, peso, velocidade ou cor. Outra alternativa seria esta:Considere agora que as medições são diversas. Se forem altura, peso e IMC, teríamos algo como a tabela abaixo. Mas aí a coluna
valuereúne valores em escalas diferentes, o que pode confundir a leitura. Nesta tabela, altura está em centímetros e peso em quilogramas:Portanto, ao converter de wide para long, você precisa decidir quais valores serão reunidos em uma coluna. Depois, definir o nome dessa coluna.
Resumindo: para converter de wide para long você precisa decidir quais colunas serão combinadas em uma única coluna. Ao fazer isso, várias colunas viram uma só, então é necessário um nome para ela, como mostram as próximas tabelas:
Observe as colunas
id1eid2na tabela acima.id2não identifica um indivíduo; é um atributo (gênero) do indivíduo. Em outras palavras, pode ser tratado como uma medição. Portanto, você pode converter para um formato ainda mais long. O formato mais "longo" possível tem três colunas:id,keyevalue.A tabela acima mostra o formato mais longo possível da Tabela 25. Porém, pessoas diferentes podem ter o mesmo nome.
Nesse caso, o long-form pode gerar ambiguidade, já que
idnão identifica unicamente a pessoa. Você pode adicionar um número após o nome para diferenciar (por exemplo, commake.unique()no R), mas não há como distinguir um nome que originalmente já tinha número. Pense em alguém que realmente se chame "John.2"!A saída óbvia é atribuir um identificador numérico distinto para cada pessoa. Nesse cenário, o nome passa a ser mais uma medição.
A próxima tabela mostra que até os nomes entram como medições. Em certo sentido, este é o formato verdadeiramente mais longo.
O formato mais longo é o mais fácil de transformar de volta em wide-form. Se você reverter o processo mostrado nas Tabelas 20 a 25, chega ao formato wide. As tabelas a seguir mostram esse processo:
O ponto-chave ao converter de wide para long é decidir quais colunas serão reunidas em uma só.
Mas não precisa ser apenas uma. Você pode usar duas colunas, se necessário, como na tabela abaixo:
Você consegue levá-la para o long-form?
As colunas
h2011,h2012,w2011,w2012significam alturas e pesos em 2011 e 2012.heighteweightestão em escalas diferentes — cm e kg. Você pode usar uma coluna só para ambos ou duas colunas, como nesta tabela:Este é long-form ou wide-form?
De long para wide no R
Vamos fazer a conversão entre long e wide no R. Existem várias funções e pacotes para isso.
Aqui, vamos ver como usar as funções
melt()edcast()do pacotereshape2. O motivo é questack()eunstack()são funções básicas e normalmente exigem pós-processamento. Jágather()espread()dotidyrtambém são muito populares, mas não serão abordadas neste tutorial.Outra função possível é
reshape(), do pacotestats. Não confunda com o pacotereshape! Esse pacote, junto com oreshape2, foi criado para quem tinha dificuldades comreshape(). Além disso,reshape()parece assumir dados longitudinais (medições repetidas ao longo do tempo).Vamos converter os dados da Tabela 35 para long-form. Suponha que a tabela abaixo esteja em um
data.framechamadodat.babies = data.frame(name= c("Jackson Smith", "Emma Williams", "Liam Brown", "Ava Wilson"), gender = c("M", "F", "M", "F"), year2011= c(74.69, NA, 88.24, 88.77), year2012=c(84.99, NA, NA, 96.45), year2013=c(91.73, 75.74, 101.83, NA)) babies
A pergunta é: "quais colunas combinar em uma só?".
Neste caso,
year2011,year2012,year2013. Ao usarmelt(), liste essas colunas emmeasure.vars:year2011,year2012,year2013estão nas colunas 3, 4 e 5, então você pode usar:O resultado é o mostrado acima. Note os nomes das colunas
variableevalue. As Tabelas 23 e 24 mostraram que novos nomes de colunas são necessários. A funçãomelt()usa por padrãovariableevalue. Você pode sobrescrever comvariable.name=evalue.name=. Veja:Nas definições acima, especificamos as medições. Em outros cenários, as colunas de identificação (
id) podem indiretamente especificar o restante. Assim, você pode escolher colunas de id em vez de medições.Os dois comandos abaixo produzem o mesmo resultado. O primeiro escolhe as colunas de id; o segundo, as colunas a serem reunidas:
Se você especificar tanto
id.varsquantomeasure.vars, as colunas que não estiverem em nenhuma dessas listas serão excluídas do resultado. Exemplo:Além disso,
na.rm=Tremove NAs:A função
dcast()faz o inverso demelt().id,variableevaluesão as colunas do formato mais longo.dcast(data, id ~ variable, value.var="value")leva do formato mais longo ao wide.babiesLongtemnamecomo id,variablecomo variável evaluecomo valor. Logo, podemos usardcast()para voltar ao wide:Conclusão
É isso! Neste tutorial, o foco foi entender a lógica e o processo de reshaping dos dados. Em geral, o long-form é preferido para análise, mas há exceções. A apresentação em wide-form pode economizar espaço quando faz sentido, porém, à medida que crescem os valores faltantes, vale mais a pena converter para long.
Na conversão de formatos, mantenha o foco no que são as medições. O lema do long-form é: uma medição por linha. No wide-form, várias medições por linha. Quando você reúne medições espalhadas por colunas em uma só coluna, os nomes originais dessas colunas precisam ser preservados em uma coluna adicional. Quando espalha os valores de uma coluna em várias colunas, é a partir da coluna
variableque você define os nomes das novas colunas.Depois que você entende o processo, usar funções como
dcast()emelt()fica muito mais simples!