Wide vs Long: Os Mesmos Dados, Dois Formatos
Toda questão de remodelagem se resume a uma distinção, então vamos vê-la. Aqui está um pequeno dataset - vendas trimestrais de duas cidades - construído nos dois formatos:
Informação idêntica, geometria diferente. O wide tem uma linha por cidade e uma coluna por trimestre - o trimestre vive nos nomes das colunas. O long tem uma linha por observação (cidade × trimestre), com o trimestre rebaixado a uma coluna comum e cada medição em uma única coluna sales.
Nenhum dos formatos é o "correto" - eles servem a senhores diferentes. Wide é o que humanos leem e planilhas exportam: compacto, comparável de relance. Long é o que as ferramentas consomem, e converter entre eles se chama pivotar (ou remodelar - a mesma coisa).
Por Que o Formato Long Vence para Análise
Olhe o que o formato wide fez com o conceito "trimestre": ele picotou uma variável em nomes de colunas. Nada consegue computar com um nome de coluna. No formato long, quarter volta a ser dado, e toda a caixa de ferramentas de análise agrupada liga:
aggregate(sales ~ quarter, ...)ougroup_by(quarter)- impossível no formato wide, onde cada trimestre é uma coluna separada que você trataria à mão (resumos agrupados todos assumem dados long).- O ggplot2 mapeia colunas para estéticas:
aes(x = quarter, y = sales, color = city)precisa que essas três colunas existam. Plotar dados wide é uma briga constante; plotar dados long é uma linha. - Adicionar o Q3 é adicionar linhas - nenhuma mudança de esquema - enquanto no formato wide surge uma coluna nova que cada etapa seguinte precisa conhecer.
A regra prática: armazene e analise em long, apresente em wide. É por isso que as duas conversões abaixo são tão usadas - os dados chegam em wide das planilhas, são alongados para análise e são alargados de novo para a tabela final do relatório.
Wide para Long: pivot_longer()
O pacote tidyr (irmão do dplyr no tidyverse) é dono da remodelagem moderna. Os trechos dele aqui são estáticos - o sandbox roda apenas R base. Alongar exige três decisões, um argumento para cada:
library(tidyr)
long <- pivot_longer(wide,
cols = c(Q1, Q2), # which columns to stack
names_to = "quarter", # new column that receives the old NAMES
values_to = "sales" # new column that receives the cell VALUES
)
Passo a passo: cols nomeia as colunas sendo dissolvidas (a sintaxe de intervalo Q1:Q2 e helpers como starts_with("Q") também funcionam - úteis quando são vinte colunas). Cada célula escolhida vira uma linha; a coluna de onde ela veio cai em quarter, o número em si em sales. As colunas não listadas em cols (aqui city) são tratadas como identificadores e se repetem pelas linhas. O resultado é exatamente o data frame long impresso acima.
Long para Wide: pivot_wider()
A viagem de volta exige duas decisões - de onde vêm os nomes das novas colunas e o que as preenche:
wide <- pivot_wider(long,
names_from = quarter, # distinct values here become new columns
values_from = sales # these values fill the cells
)
Cada valor distinto de quarter (Q1, Q2) vira uma coluna; cada célula é preenchida com o valor de sales da linha que casa com aquela cidade e trimestre. As colunas restantes (city) atuam como identificadores de linha - uma linha de saída por combinação distinta. Uma cidade sem determinado trimestre recebe NA naquela célula (o argumento values_fill substitui por outra coisa, por exemplo values_fill = 0 para dados de contagem).
Você também vai encontrar a geração anterior em tutoriais mais antigos: spread() é o pivot_wider() e gather() é o pivot_longer() - superados desde o tidyr 1.0, ainda funcionando, sem valer a pena aprender além de reconhecê-los.
O R Base Tem o reshape() - Um Aviso Honesto
O R base consegue fazer isso sem pacotes, via reshape() - uma função tão famosamente confusa que a própria documentação historicamente se desculpava por ela. Ela foi projetada em torno do vocabulário de estudos longitudinais (idvar, timevar, direction), os nomes dos argumentos se encaixam mal em dados do dia a dia, e todo mundo os esquece entre um uso e outro. Mas funciona:
Repare nos nomes da saída: sales.Q1, sales.Q2 - o nome da coluna de valores fundido em cada uma. Serve num aperto, em um ambiente sem dependências, ou quando você o encontra em código antigo. Mas se você remodela dados mais de uma vez por ano, install.packages("tidyr") é a recomendação honesta - esta é a única tarefa de manipulação em que a ferramenta do R base genuinamente custa mais do que a dependência que ela economiza.
A Armadilha das Chaves Duplicadas ao Alargar
Alargar assume que cada combinação de identificador + nome determina um valor. Se Lima tem duas linhas Q1, qual número vai na única célula Q1? O pivot_wider() se recusa a adivinhar: emite um aviso (values are not uniquely identified) e coloca uma list-column na célula - um data frame com listas aninhadas dentro, o que quebra a próxima coisa que você fizer com ele.
Quando você vir esse aviso, não corra primeiro para a válvula de escape values_fn - pergunte por que as duplicatas existem. Geralmente os dados estão em uma granularidade mais fina do que você pensava (linhas diárias, não trimestrais - então resuma primeiro, depois alargue) ou um join anterior duplicou linhas. values_fn = mean (ou sum) é a correção legítima só quando você consegue dizer em voz alta sob qual agregação as duplicatas devem colapsar. O reshape() é pior aqui: ele mantém silenciosamente a primeira duplicata e descarta o resto, com apenas um aviso fácil de passar batido.
O Que Você Leva
- Wide: variáveis escondidas nos nomes das colunas, feito para leitura. Long: uma linha por observação, feito para análise e para o ggplot2.
- Armazene e analise em long, apresente em wide.
pivot_longer(cols, names_to, values_to)empilha colunas em linhas; colunas não listadas viram identificadores repetidos.pivot_wider(names_from, values_from)espalha linhas em colunas; as lacunas são preenchidas comNA.spread()/gather()são os nomes antigos; oreshape()base funciona, mas é famosamente desajeitado.- Pares identificador + nome duplicados tornam o alargamento ambíguo - resuma primeiro, não apenas silencie o aviso.
A seguir: lendo dados reais de arquivos - o read.csv() e suas arestas cortantes.
Perguntas frequentes
Qual é a diferença entre dados wide e long no R?
Mesmos dados, formatos diferentes. O formato wide espalha uma variável por várias colunas (uma coluna por trimestre, digamos) - uma linha por sujeito, feito para leitura humana. O formato long empilha tudo em linhas - uma linha por observação, com uma coluna de nomes e uma coluna de valores - feito para análise agrupada e para o ggplot2.
Como converto dados wide para long no R?
O pivot_longer(df, cols = Q1:Q4, names_to = "quarter", values_to = "sales") do tidyr empilha as colunas escolhidas em duas novas: os nomes das colunas antigas vão para a coluna names_to, e os valores das células para a coluna values_to.
Como converto dados long para wide no R?
O pivot_wider(df, names_from = quarter, values_from = sales) do tidyr espalha linhas em colunas: cada valor distinto de names_from vira uma coluna, preenchida com as entradas correspondentes de values_from. Combinações ausentes viram NA.
O que substituiu spread e gather no R?
pivot_wider() substituiu spread() e pivot_longer() substituiu gather() no tidyr 1.0 (2019). As funções antigas ainda funcionam - você as verá em tutoriais mais antigos - mas todo código novo deve usar o par pivot_*, que tem argumentos mais claros e mais recursos.