Sériation en R : réordonner pour révéler la structure
Trouvez l’ordre des lignes et des colonnes qui fait apparaître les blocs d’une matrice, d’une matrice de distance ou de corrélation — avec le package seriation
Data Visualization
Une heatmap en ordre alphabétique ou arbitraire cache sa structure ; le bon ordre des lignes et des colonnes la révèle. Ce guide pratique et visuel utilise le package seriation en R pour réordonner une matrice de distance, une matrice de données brutes et une matrice de corrélation sur le jeu de données intégré mtcars — avec un avant/après que vous pouvez reproduire, et un guide clair sur la méthode à choisir (OLO, TSP, basée sur l’angle).
Pourquoi une heatmap en ordre alphabétique ou arbitraire cache sa structure — et comment réordonner les lignes et les colonnes fait apparaître le motif.
La sériation en une idée : trouver l’ordre linéaire des objets qui place les éléments similaires les uns à côté des autres, pour que les blocs se posent sur la diagonale.
Le flux de travail central avec le package seriation — seriate() une matrice de distance, extraire l’ordre avec get_order(), l’appliquer avec permute().
Un avant/après que vous pouvez exécuter : une matrice de distance, une matrice de données brutes (lignes et colonnes) et une matrice de corrélation.
Quelle méthode choisir — OLO, TSP, basée sur l’angle — sous forme de table claire, plus l’ordonnancement d’une matrice de corrélation avec le package ggcorrplot. Chaque bloc est du base R sur les données intégrées mtcars — copiez-le et exécutez-le en local pour reproduire les figures.
Vous avez construit une heatmap, et elle ressemble à de la neige. Les couleurs sont là, mais aucun motif ne saute aux yeux — parce que les lignes et les colonnes sont dans l’ordre où elles sont arrivées (alphabétique, ou l’ordre de votre data frame). Cet ordre ne porte aucun sens, et il disperse les lignes apparentées un peu partout dans le graphique. La sériation corrige cela. C’est le problème qui consiste à trouver un ordonnancement unidimensionnel d’un ensemble d’objets de sorte que les objets similaires soient proches. Réordonnez les lignes et les colonnes d’une heatmap par une bonne sériation et sa structure en blocs cachée — des groupes de lignes similaires, des regroupements de variables corrélées — se cale sur la diagonale, là où votre œil peut la lire.
Quelques termes d’abord, car ils reviennent plus bas. Une matrice de distance (ou de dissimilarité) enregistre à quelle distance se trouve chaque paire d’objets — en R, la sortie de dist(). Une permutation est simplement un réordonnancement des objets (la ligne 3 devient la ligne 1, et ainsi de suite). L’ordonnancement optimal des feuilles (OLO, optimal leaf ordering) est une façon spécifique et déterministe de produire cette permutation à partir d’un dendrogramme — l’arbre que construit la classification hiérarchique — en faisant pivoter les branches de l’arbre (sans les rompre) pour placer les feuilles les plus similaires les unes à côté des autres. C’est le cheval de trait sur lequel nous nous appuyons.
Le problème : un ordre arbitraire cache la structure
Commençons par une matrice de distance. Nous mettons à l’échelle les données intégrées mtcars (32 voitures × 11 mesures) pour que chaque variable soit sur une base comparable, puis nous calculons la distance euclidienne entre chaque paire de voitures avec dist(). Tracée en heatmap en ordre alphabétique, les faibles distances (voitures similaires) sont claires et les grandes distances (voitures différentes) sont sombres :
library(seriation)library(ggplot2)d <-dist(scale(mtcars)) # pairwise distances between the 32 carsM <-as.matrix(d)alpha <-sort(rownames(M)) # arbitrary order: alphabeticalMa <- M[alpha, alpha]df <-as.data.frame(as.table(Ma)) # base-R reshape: Var1, Var2, Freqggplot(df, aes(Var2, Var1, fill = Freq)) +geom_tile() +scale_fill_viridis_c(option ="mako", direction =-1, name ="distance") +labs(x =NULL, y =NULL, title ="Distance matrix in alphabetical order") +theme_minimal(base_size =7) +theme(axis.text.x =element_text(angle =90, hjust =1, vjust =0.5))
Hormis la diagonale claire — où chaque voiture se trouve à distance zéro d’elle-même — ce n’est que du bruit. Il existe bien des groupes de voitures similaires dans mtcars (voitures économiques, muscle cars, voitures de sport), mais l’ordre alphabétique disperse chaque groupe à travers le graphique, si bien qu’aucun bloc ne se forme jamais. Les données ont une structure ; c’est l’ordre qui la cache.
Ce que fait la sériation
La sériation recherche une permutation des objets qui minimise un coût — typiquement, la distance totale entre objets voisins dans l’ordre (autrement dit : rendre les lignes consécutives aussi similaires que possible). Lorsque vous réordonnez ensuite la heatmap par cette permutation, les objets similaires deviennent adjacents, si bien que les tuiles de faible distance (claires) se rassemblent en blocs le long de la diagonale.
La valeur par défaut la plus fiable est OLO (optimal leaf ordering, ordonnancement optimal des feuilles). Elle exécute d’abord une classification hiérarchique pour construire un dendrogramme, puis trouve les rotations de branches qui ordonnent les feuilles de façon optimale — le meilleur ordonnancement cohérent avec cet arbre de classification. Deux propriétés en font le choix sûr : elle respecte la structure des regroupements (l’ordre et un dendrogramme s’accordent donc), et elle est déterministe — les mêmes données donnent toujours le même ordre, ce qui importe pour des figures reproductibles.
La révélation : sérier une matrice de distance
Le flux de travail tient en trois fonctions. seriate() calcule l’ordonnancement, get_order() l’extrait sous forme de vecteur d’entiers (ou de noms) simple, et permute() l’applique à l’objet. Voici ce que cela donne sur notre matrice de distance :
library(seriation)d <-dist(scale(mtcars))o <-seriate(d, method ="OLO") # optimal leaf ordering (deterministic)ord <-get_order(o) # the permutation, as a vectorhead(names(ord), 8)
ord est le nouvel ordre des voitures — les berlines lourdes à un bout, les petites voitures économiques à l’autre, avec tout ce qui est gradué entre les deux. Appliquez-le maintenant aux deux marges de la matrice et redessinez. La matrice réordonnée peut s’obtenir soit par indexation (M[ord, ord]), soit, de façon équivalente, avec la fonction permute() propre à seriation, qui prend un ordonnancement par dimension :
library(seriation)library(ggplot2)d <-dist(scale(mtcars))o <-seriate(d, method ="OLO")M <-as.matrix(d)Ms <-permute(M, c(o, o)) # reorder rows and columns by the seriation# identical to: M[get_order(o), get_order(o)]df <-as.data.frame(as.table(Ms))ggplot(df, aes(Var2, Var1, fill = Freq)) +geom_tile() +scale_fill_viridis_c(option ="mako", direction =-1, name ="distance") +labs(x =NULL, y =NULL, title ="Distance matrix after seriation (OLO)") +theme_minimal(base_size =7) +theme(axis.text.x =element_text(angle =90, hjust =1, vjust =0.5))
Mêmes données, mêmes distances — seul l’ordre a changé, et la structure est désormais évidente. Des blocs clairs se posent sur la diagonale : les berlines compactes Mercedes se regroupent, les voitures économiques (Corolla, Fiat, Civic) forment leur propre bloc, et les lourdes muscle cars (Cadillac, Lincoln, Chrysler) ancrent le coin le plus éloigné. La matrice entière se lit comme un dégradé continu d’un « type » de voiture au suivant. Ce contraste — la même figure, illisible puis lisible — est tout l’intérêt de la sériation.
Réordonner une matrice de données brutes (lignes et colonnes)
Vous n’avez pas besoin d’une matrice de distance pour commencer. Vous pouvez sérier directement une matrice de données brutes — et ici les lignes et les colonnes reçoivent des ordres différents, parce que les voitures et les mesures sont des choses de nature différente. La recette propre et reproductible consiste à sérier chaque marge selon ses propres distances : ordonner les lignes (voitures) par dist(X), et les colonnes (variables) par dist(t(X)), toutes deux avec OLO.
library(seriation)library(ggplot2)X <-scale(mtcars) # 32 cars x 11 measurementsrow_ord <-get_order(seriate(dist(X), method ="OLO")) # order the carscol_ord <-get_order(seriate(dist(t(X)), method ="OLO")) # order the variablesXs <- X[row_ord, col_ord]df <-as.data.frame(as.table(Xs))ggplot(df, aes(Var2, Var1, fill = Freq)) +geom_tile() +scale_fill_viridis_c(option ="viridis", name ="z-score") +labs(x =NULL, y =NULL, title ="mtcars values, rows and columns seriated") +theme_minimal(base_size =7) +theme(axis.text.x =element_text(angle =90, hjust =1, vjust =0.5))
Lisez-la dans deux directions à la fois. Le long des lignes, les voitures vont des plus lourdes aux plus légères. À travers les colonnes, les onze mesures se scindent en deux groupes cohérents : un bloc taille-et-puissance (wt, disp, cyl, hp, carb) et un bloc efficacité (mpg, drat, vs, am, gear, qsec). Les voitures lourdes sont vives sur le premier bloc et sombres sur le second ; les voitures légères s’inversent. Ce dégradé à double sens est exactement l’aspect « heatmap regroupée » — et il est apparu du seul fait d’ordonner chaque marge, sans aucun regroupement manuel.
Quelle méthode utiliser ?
seriate() propose de nombreuses méthodes (voir list_seriation_methods("dist")). Vous en avez rarement besoin de plus de trois, et le choix se résume à ce que vous voulez optimiser dans l’ordre et à savoir si vous avez besoin qu’il soit reproductible. Les trois ci-dessous s’exécutent sur un objet dist :
Méthode
Ce qu’elle optimise
À privilégier quand
"OLO"
Le meilleur ordre des feuilles cohérent avec un dendrogramme (déterministe)
Le choix par défaut sûr — vous montrez aussi un dendrogramme, et vous avez besoin d’une figure reproductible.
"TSP"
Le chemin de voisinage le plus serré (distance totale la plus courte), via un solveur de voyageur de commerce
Vous voulez le dégradé le plus lisse possible et n’avez pas besoin que l’ordre corresponde à une classification précise. Utilise des redémarrages aléatoires — set.seed() pour un résultat reproductible.
"MDS_angle"
Un ordre rapide à partir de l’angle des points dans une projection en faible dimension
De grandes matrices où vous voulez un ordonnancement rapide et peu coûteux.
Vous n’avez pas à deviner quel ordre est le plus « serré » — criterion() note tout ordonnancement au regard des distances. Une longueur de chemin plus faible signifie un ordre plus lisse :
Ici, OLO donne le chemin le plus court (le dégradé le plus serré), devançant TSP — dont l’heuristique à redémarrages aléatoires n’atteint pas toujours l’optimum sur un petit problème comme celui-ci. Ainsi, sur ces données, la méthode déterministe, cohérente avec le dendrogramme et sans graine est aussi la plus serrée : OLO est la valeur par défaut naturelle, et criterion() vous permet de le confirmer plutôt que de le deviner.
Ordonner une matrice de corrélation avec ggcorrplot
L’endroit le plus courant où l’on rencontre ce problème est une matrice de corrélation. Dans l’ordre des variables, les corrélations ressemblent à un patchwork aléatoire de rouge et de bleu ; sériées, les variables mutuellement corrélées se rassemblent en blocs. Nous utilisons le package ggcorrplot du fondateur pour la dessiner. D’abord, la corrélation de mtcars en simple ordre alphabétique :
library(ggcorrplot)corr <-cor(mtcars)alpha <-sort(rownames(corr))ggcorrplot(corr[alpha, alpha]) + ggplot2::ggtitle("Correlation in alphabetical order")
Un damier — vous ne pouvez pas dire quelles variables évoluent ensemble. Sérions maintenant. Une matrice de corrélation n’est pas une distance, aussi la transformons-nous d’abord en distance : 1 - corr est petit lorsque deux variables sont fortement corrélées positivement, ce qui est exactement la « proximité » selon laquelle nous voulons ordonner. Sériez cette distance avec OLO, puis appliquez l’ordre à la matrice de corrélation avant de la tracer :
library(seriation)library(ggcorrplot)corr <-cor(mtcars)o <-seriate(as.dist(1- corr), method ="OLO") # 1 - corr = a distanceord <-get_order(o)ggcorrplot(corr[ord, ord]) + ggplot2::ggtitle("Correlation after seriation (OLO)")
Maintenant, elle se lit. Deux blocs rouges se posent sur la diagonale — les variables taille-et-puissance (wt, disp, cyl, hp, carb) évoluent toutes ensemble, et les variables d’efficacité (mpg, drat, am, vs, qsec, plus gear) forment l’autre bloc — tandis que les fortes corrélations négatives entre les deux groupes sont proprement repoussées dans les coins. ggcorrplot() dispose aussi d’un raccourci intégré, ggcorrplot(corr, hc.order = TRUE), qui réordonne pour vous par classification hiérarchique ; sérier la distance vous-même, comme ci-dessus, vous laisse le plein choix de la méthode (OLO, TSP, angle) et un flux de travail cohérent entre heatmaps et matrices de corrélation. (Le package base-R corrplot possède aussi un argument order =, mais ggcorrplot vous garde dans ggplot2, ce qui vous permet de le thématiser et de le combiner comme n’importe quel autre graphique.)
Réordonner pour révéler — une habitude de data-viz
La leçon dure plus longtemps que le package : l’ordre d’une heatmap est un choix de conception, et la valeur par défaut (alphabétique, ou l’ordre du data frame) est presque toujours le mauvais. Chaque fois que vous dessinez une matrice, une matrice de distance, une matrice de corrélation ou une heatmap regroupée, demandez-vous quel ordre rendrait sa structure visible — et réordonnez pour la révéler. C’est aussi un endroit rapide et fiable pour contrôler du code généré : un extrait qui trace cor(df) ou un dist() directement en heatmap affichera quelque chose, mais il saute silencieusement l’étape d’ordonnancement, si bien que la figure paraît sans motif même quand les données sont richement structurées. Si votre heatmap ressemble à du bruit, le remède n’est généralement pas plus de données ou une autre palette — c’est un meilleur ordre des lignes et des colonnes.
Problèmes courants
Ma heatmap paraît toujours aléatoire après réordonnancement. Vous avez presque certainement réordonné le graphique mais pas les données — ou vous n’avez appliqué l’ordre qu’à une seule marge. Une matrice de distance ou de corrélation est symétrique, elle doit donc être permutée sur les deux lignes et colonnes avec le même ordre : M[ord, ord], et non M[ord, ]. Vérifiez que get_order() a bien renvoyé une permutation de longueur complète et que vous avez indexé les deux dimensions.
seriate() sur une matrice et sur un dist se comportent différemment. Passer un objet dist série les objets (un seul ordre, appliqué aux deux marges de la matrice symétrique). Passer une matrice simple la série comme une table de données, ordonnant les lignes et les colonnes indépendamment — et certaines méthodes matricielles (comme BEA) exigent une matrice non négative et échoueront sur des données standardisées. Si vous voulez un ordonnancement unique des objets, passez un dist ; si vous voulez des ordres séparés pour lignes/colonnes, sériez dist(X) et dist(t(X)) comme montré ci-dessus.
Mon ordre TSP change à chaque exécution. La méthode "TSP" utilise des redémarrages aléatoires, elle est donc non déterministe à moins de fixer la graine. Appelez set.seed() juste avant seriate(..., method = "TSP"), ou utilisez "OLO", qui est déterministe par construction et ne nécessite aucune graine — le meilleur choix quand vous voulez une figure qui se reproduit à l’identique.
Questions fréquentes
NoteComment réordonner une heatmap en R ?
Calculez une matrice de distance avec dist(), ordonnez-la avec le package seriation — o <- seriate(d, method = "OLO") — extrayez la permutation avec ord <- get_order(o), puis appliquez cet ordre aux deux lignes et colonnes de votre matrice avant de la tracer : M[ord, ord]. Dessiner cette matrice réordonnée avec geom_tile() (ou pheatmap, ou ggcorrplot pour une matrice de corrélation) place les lignes similaires les unes à côté des autres, si bien que la structure en blocs se pose sur la diagonale.
NoteQu’est-ce que la sériation ?
La sériation, c’est trouver un ordonnancement unidimensionnel d’un ensemble d’objets qui place les objets similaires les uns près des autres. À partir d’une matrice de distance ou de dissimilarité, elle recherche la permutation qui minimise un coût — généralement la distance totale entre objets voisins. Réordonner une heatmap ou une matrice par cette permutation en révèle la structure : des regroupements et des blocs qu’un ordre arbitraire (alphabétique ou l’ordre du data frame) dispersait se rassemblent le long de la diagonale. L’implémentation R est le package seriation.
NoteQuelle est la différence entre l’ordre de la sériation et celui de la classification hiérarchique ?
La classification hiérarchique construit un arbre (dendrogramme) ; tout dendrogramme peut se dessiner dans de nombreux ordres de feuilles également valides, car chaque branche peut être retournée sans changer la classification. La sériation choisit lequel de ces ordres utiliser. L’ordonnancement optimal des feuilles (method = "OLO") est le pont : il prend l’arbre de classification et fait pivoter ses branches pour rendre adjacentes les feuilles les plus similaires — le meilleur ordre linéaire cohérent avec l’arbre. D’autres méthodes de sériation (comme TSP) ignorent totalement l’arbre et optimisent l’ordre directement, ce qui peut donner un dégradé plus lisse mais aucun dendrogramme correspondant.
NoteQuelle méthode de sériation dois-je utiliser ?
Commencez par "OLO" (ordonnancement optimal des feuilles) : elle est déterministe, respecte un dendrogramme et produit des figures reproductibles — le choix par défaut sûr. Utilisez "TSP" quand vous voulez l’ordonnancement de voisinage le plus serré possible (le dégradé le plus lisse) et n’avez pas besoin qu’il corresponde à un arbre de classification, mais fixez d’abord une graine car elle utilise des redémarrages aléatoires. Utilisez une méthode basée sur l’angle comme "MDS_angle" pour un ordre rapide et peu coûteux sur de grandes matrices. Vous pouvez comparer objectivement n’importe quels ordonnancements avec criterion(d, o, method = "Path_length") — plus bas signifie un ordre plus lisse.
NoteComment ordonner une matrice de corrélation en R ?
Une matrice de corrélation n’est pas une distance, convertissez-la donc d’abord : 1 - corr est petit lorsque deux variables sont fortement corrélées positivement. Sériez-la avec o <- seriate(as.dist(1 - corr), method = "OLO"), obtenez l’ordre avec get_order(o), et appliquez-le : corr[ord, ord]. Tracez la matrice réordonnée avec ggcorrplot() et les variables corrélées se rassemblent en blocs rouges sur la diagonale. En raccourci d’une ligne, ggcorrplot(corr, hc.order = TRUE) réordonne pour vous par classification hiérarchique.
Testez votre compréhension
ImportantÀ vous de jouer : révéler la structure dans un nouveau jeu de données
Prenez les données intégrées USArrests (taux de crimes violents dans les 50 États américains). Standardisez-les, construisez une matrice de distance entre les États, et dessinez la heatmap de distance deux fois — une fois en ordre alphabétique, une fois après sériation avec OLO. Confirmez que la version sériée montre sur la diagonale des blocs d’États similaires que la version alphabétique cache.
AstuceIndice
La recette est identique à l’exemple de distance sur mtcars. Partez de d <- dist(scale(USArrests)), puis sort(rownames(...)) pour l’ordre « avant » et get_order(seriate(d, method = "OLO")) pour l’ordre « après ». Remodelez chaque matrice avec as.data.frame(as.table(...)) et tracez avec geom_tile().
AstuceSolution
library(seriation)library(ggplot2)d <-dist(scale(USArrests))M <-as.matrix(d)# BEFORE: alphabeticalalpha <-sort(rownames(M))# AFTER: seriatedord <-get_order(seriate(d, method ="OLO"))draw <-function(mat, title) { df <-as.data.frame(as.table(mat))ggplot(df, aes(Var2, Var1, fill = Freq)) +geom_tile() +scale_fill_viridis_c(option ="mako", direction =-1, name ="distance") +labs(x =NULL, y =NULL, title = title) +theme_minimal(base_size =6) +theme(axis.text.x =element_text(angle =90, hjust =1, vjust =0.5))}draw(M[alpha, alpha], "USArrests: alphabetical") # patternlessdraw(M[ord, ord], "USArrests: seriated (OLO)") # blocks on the diagonal
La heatmap sériée regroupe les États aux profils criminels similaires — un dégradé diagonal clair que l’ordre alphabétique disperse en bruit.
NoteVérification rapide
Avant de sérier une matrice de corrélation, vous la convertissez avec as.dist(1 - corr). Pourquoi ?
A. Pour rendre la matrice symétrique.
B. Parce que seriate() ordonne par distance, et 1 - corr transforme une forte corrélation positive en une petite distance.
C. Pour supprimer les corrélations négatives.
D. Parce que seriate() ne peut pas lire une matrice numérique.
AstuceAfficher la réponse
B.seriate() ordonne par distance, où petit signifie proche. Une corrélation de +1 doit rendre deux variables adjacentes, elle doit donc correspondre à la plus petite distance — et 1 - 1 = 0. Une corrélation de -1 correspond à une distance de 2 (aussi éloignées que possible). Sérier cette distance regroupe les variables mutuellement positives en blocs sur la diagonale ; passer la matrice de corrélation brute l’ordonnerait à l’envers.
Conclusion
L’ordre des lignes et des colonnes d’une heatmap relève de la visualisation de données, pas de la comptabilité. Laissées en ordre alphabétique ou en ordre du data frame, même des données richement structurées se lisent comme du bruit ; une bonne sériation — seriate() une distance, get_order(), l’appliquer aux deux marges — rassemble la structure sur la diagonale où vous pouvez la voir. Optez pour OLO comme valeur par défaut déterministe, TSP quand vous voulez le dégradé le plus serré (avec une graine), et une méthode basée sur l’angle pour la rapidité sur de grandes matrices. Qu’il s’agisse d’une matrice de distance, d’une matrice de données brutes ou d’une matrice de corrélation dessinée avec ggcorrplot, l’habitude est la même : réordonner pour révéler.
Pour aller plus loin dans /learn
La sériation est un outil de réordonnancement ; la structure qu’elle révèle vient du clustering et des distances. Pour les fondations, avec des tutoriels vérifiés par la reproductibilité et du code en direct :
Heatmap de clustering en R — construire des heatmaps annotées et regroupées de bout en bout (le réordonnancement que la sériation automatise).
Demandez à Prova« réordonne ma matrice de corrélation en R pour que les variables corrélées se regroupent, et dessine-la avec ggcorrplot » — elle répond avec du code que vous pouvez exécuter sur vos propres données. The runtime is the judge.Demander à Prova →
Cette page vous a-t-elle été utile ?
Merci pour votre retour !
Recevez les nouvelles leçons R & Python par e-mail
Pratique, reproductible, sans spam. Désinscription à tout moment.
Double opt-in. Nous ne partageons jamais votre e-mail.
@online{kassambara2026,
author = {Kassambara, Alboukadel},
title = {Sériation en R : réordonner pour révéler la structure},
date = {2026-07-18},
url = {https://www.datanovia.com/blog/seriation-in-r},
langid = {fr}
}