Menu

Remettre en forme des données en R : pivot_wider et pivot_longer (large ou long)

Les formats large et long et comment passer de l'un à l'autre : pivot_longer() et pivot_wider() de tidyr, les anciens noms spread/gather, et reshape() de R de base.

Cette page contient des éditeurs exécutables - modifiez, exécutez et voyez la sortie instantanément.

Large ou long : les mêmes données, deux formes

Toute question de remise en forme se ramène à une seule distinction, alors voyons-la. Voici un petit jeu de données - les ventes trimestrielles de deux villes - construit dans les deux formes :

Information identique, géométrie différente. Le format large a une ligne par ville et une colonne par trimestre - le trimestre vit dans les noms de colonnes. Le format long a une ligne par observation (ville × trimestre), avec le trimestre rétrogradé en colonne ordinaire et toutes les mesures dans une seule colonne sales.

Aucune forme n'est « correcte » - elles servent des maîtres différents. Le large est ce que lisent les humains et ce qu'exportent les tableurs : compact, comparable d'un coup d'œil. Le long est ce que consomment les outils, et passer de l'un à l'autre s'appelle pivoter (ou remettre en forme - même chose).

Pourquoi le format long gagne pour l'analyse

Regarde ce que le format large a fait au concept de « trimestre » : il a déchiqueté une variable en noms de colonnes. Rien ne peut calculer avec un nom de colonne. En format long, quarter redevient une donnée, et toute la trousse d'analyse groupée s'allume :

  • aggregate(sales ~ quarter, ...) ou group_by(quarter) - impossible en format large, où chaque trimestre est une colonne distincte à traiter à la main (les résumés groupés supposent tous des données longues).
  • ggplot2 associe des colonnes à des esthétiques : aes(x = quarter, y = sales, color = city) a besoin que ces trois colonnes existent. Tracer des données larges est un combat permanent ; tracer des données longues tient en une ligne.
  • Ajouter le Q3 revient à ajouter des lignes - aucun changement de schéma - là où le format large fait pousser une nouvelle colonne dont chaque étape en aval doit être informée.

La règle pratique : stocke et analyse en long, présente en large. C'est pourquoi les deux conversions ci-dessous servent tant - les données arrivent larges des tableurs, sont allongées pour l'analyse, puis réélargies pour le tableau final du rapport.

Large vers long : pivot_longer()

Le package tidyr (frère de dplyr dans le tidyverse) gouverne la remise en forme moderne. Ses extraits sont statiques ici - le bac à sable n'exécute que du R de base. L'allongement demande trois décisions, un argument chacune :

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
)

Déroule-le : cols nomme les colonnes dissoutes (la syntaxe de plage Q1:Q2 et des helpers comme starts_with("Q") marchent aussi - pratique quand il y en a vingt). Chaque cellule choisie devient une ligne ; la colonne d'où elle vient atterrit dans quarter, le nombre lui-même dans sales. Les colonnes non listées dans cols (ici city) sont traitées comme des identifiants et se répètent sur les lignes. Le résultat est exactement le tableau long affiché plus haut.

Long vers large : pivot_wider()

Le voyage inverse demande deux décisions - d'où viennent les nouveaux noms de colonnes, et ce qui les remplit :

wide <- pivot_wider(long,
    names_from  = quarter,   # distinct values here become new columns
    values_from = sales      # these values fill the cells
)

Chaque valeur distincte de quarter (Q1, Q2) devient une colonne ; chaque cellule est remplie avec la valeur sales de la ligne correspondant à cette ville et ce trimestre. Les colonnes restantes (city) jouent le rôle d'identifiants de lignes - une ligne de sortie par combinaison distincte. Une ville à laquelle manque un trimestre reçoit NA dans cette cellule (l'argument values_fill substitue autre chose, par exemple values_fill = 0 pour des données de comptage).

Tu croiseras aussi la génération précédente dans les tutoriels plus anciens : spread() c'est pivot_wider() et gather() c'est pivot_longer() - remplacés depuis tidyr 1.0, toujours fonctionnels, pas la peine de les apprendre au-delà de savoir les reconnaître.

R de base a reshape() - un avertissement honnête

R de base sait le faire sans package, via reshape() - une fonction si célèbre pour sa confusion que sa propre documentation s'en est historiquement excusée. Elle a été conçue autour du vocabulaire des études longitudinales (idvar, timevar, direction), les noms d'arguments s'appliquent maladroitement aux données du quotidien, et tout le monde les oublie entre deux usages. Ça marche, cela dit :

Note les noms de sortie : sales.Q1, sales.Q2 - le nom de la colonne de valeurs fusionné à chacun. Ça dépanne, dans un environnement sans dépendances, ou quand tu la croises dans du vieux code. Mais si tu remets des données en forme plus d'une fois par an, install.packages("tidyr") est la recommandation honnête - c'est la seule tâche de manipulation où l'outil de R de base coûte réellement plus cher que la dépendance qu'il évite.

Le piège des clés en double lors de l'élargissement

L'élargissement suppose que chaque combinaison identifiant + nom désigne une valeur. Si Lima a deux lignes Q1, quel nombre va dans l'unique cellule Q1 ? pivot_wider() refuse de deviner : il émet un avertissement (values are not uniquely identified) et met une colonne-liste dans la cellule - un data frame avec des listes imbriquées, ce qui casse la suite de ton traitement.

Quand tu vois cet avertissement, ne saute pas d'abord sur la soupape values_fn - demande pourquoi il y a des doublons. Généralement les données sont d'une granularité plus fine que tu ne le pensais (lignes quotidiennes, pas trimestrielles - alors résume d'abord, puis élargis) ou une jointure en amont a dupliqué des lignes. values_fn = mean (ou sum) n'est la correction légitime qu'une fois que tu peux dire à voix haute sous quelle agrégation les doublons doivent se réduire. reshape() est pire ici : il garde silencieusement le premier doublon et jette le reste, avec seulement un avertissement facile à dépasser en défilant.

Ce que tu retiens

  • Large : des variables cachées dans les noms de colonnes, fait pour la lecture. Long : une ligne par observation, fait pour l'analyse et ggplot2.
  • Stocke et analyse en long, présente en large.
  • pivot_longer(cols, names_to, values_to) empile des colonnes en lignes ; les colonnes non listées deviennent des identifiants répétés.
  • pivot_wider(names_from, values_from) étale des lignes en colonnes ; les trous se remplissent de NA.
  • spread()/gather() sont les anciens noms ; le reshape() de base fonctionne mais est réputé peu commode.
  • Des paires identifiant + nom en double rendent l'élargissement ambigu - résume d'abord, ne te contente pas de faire taire l'avertissement.

Prochaine étape : lire de vraies données depuis des fichiers - read.csv() et ses angles vifs.

Questions fréquentes

Quelle est la différence entre données larges et longues en R ?

Mêmes données, formes différentes. Le format large étale une variable en colonnes (une colonne par trimestre, disons) - une ligne par sujet, fait pour la lecture humaine. Le format long l'empile en lignes - une ligne par observation, avec une colonne de noms et une colonne de valeurs - fait pour l'analyse groupée et ggplot2.

Comment convertir des données larges en format long en R ?

pivot_longer(df, cols = Q1:Q4, names_to = "quarter", values_to = "sales") de tidyr empile les colonnes choisies en deux nouvelles : les anciens noms de colonnes vont dans la colonne names_to, les valeurs des cellules dans la colonne values_to.

Comment convertir des données longues en format large en R ?

pivot_wider(df, names_from = quarter, values_from = sales) de tidyr étale les lignes en colonnes : chaque valeur distincte de names_from devient une colonne, remplie avec les entrées values_from correspondantes. Les combinaisons manquantes deviennent NA.

Qu'est-ce qui a remplacé spread et gather en R ?

pivot_wider() a remplacé spread() et pivot_longer() a remplacé gather() dans tidyr 1.0 (2019). Les anciennes fonctions marchent toujours - tu les verras dans des tutoriels plus anciens - mais tout code neuf devrait utiliser la paire pivot_*, aux arguments plus clairs et aux fonctionnalités plus riches.

Coddy programming languages illustration

Apprendre à coder avec Coddy

COMMENCER