P-value en classification hiérarchique avec R (pvclust)
Distinguez les vrais regroupements du bruit : utilisez le rééchantillonnage bootstrap pour attribuer une p-value AU et BP à chaque branche de votre dendrogramme, et encadrez les regroupements que les données soutiennent réellement
Vos regroupements de dendrogramme sont-ils réels ou un simple bruit d’échantillonnage ? Le package pvclust répond avec une p-value par branche. Cette leçon exécute pvclust() sur des données d’expression génique, lit les p-values AU (approximately unbiased) et BP (bootstrap probability) affichées sur l’arbre, met en évidence les regroupements fortement soutenus avec pvrect(), les extrait avec pvpick(), et explique pourquoi l’AU est la p-value à laquelle se fier.
Date de publication
24 juin 2026
Modifié
7 juillet 2026
AstucePoints clés
Un dendrogramme produit toujours des regroupements — même à partir de pur bruit. pvclust vous indique lesquels de ces regroupements sont réels en attachant une p-value à chaque branche.
Il procède par rééchantillonnage bootstrap : il reconstruit l’arbre des milliers de fois sur des données rééchantillonnées et demande, pour chaque regroupement, à quelle fréquence ce groupe exact réapparaît-il ?
Chaque branche reçoit deux nombres : AU (Approximately Unbiased, en rouge) et BP (Bootstrap Probability, en vert). L’AU est celui auquel se fier — il corrige un biais connu de la BP.
Les regroupements dont l’AU ≥ 95 % sont fortement soutenus par les données.pvrect() les encadre sur l’arbre ; pvpick() en extrait les membres.
pvclust() regroupe les colonnes de vos données. Pour regrouper les lignes (le cas habituel), transposez d’abord avec t().
Vous exécutez une classification hiérarchique, coupez l’arbre, et obtenez quatre groupes bien nets. Mais voici la vérité dérangeante : un dendrogramme vous livrera des regroupements même si les données sont du pur bruit. L’algorithme fusionne toujours quelque chose. Alors avant de construire un récit autour du « regroupement 3 », vous devriez poser la question honnête : ces regroupements sont-ils réels, ou un artefact de cet échantillon particulier ?
C’est exactement la question à laquelle répond une p-value pour un regroupement. Le package R pvclust attribue une p-value à chaque branche du dendrogramme par rééchantillonnage bootstrap — il reconstruit l’arbre de nombreuses fois sur des versions rééchantillonnées de vos données et mesure à quelle fréquence chaque regroupement réapparaît. Un regroupement qui revient encore et encore est bien soutenu ; un qui n’apparaît que par chance ne l’est pas.
À utiliser lorsque :
vous devez défendre une classification dans un article ou un rapport (les relecteurs demandent « est-ce significatif ? »),
vous regroupez des échantillons en génomique / données d’expression (le terrain de prédilection de pvclust), ou
vous voulez une règle d’arrêt objective pour savoir où finit la vraie structure et où commence le bruit.
La sortie est un dendrogramme familier avec deux p-values affichées à chaque branche, et une boîte tracée autour de chaque regroupement que les données soutiennent véritablement.
NoteL’algorithme bootstrap, en une phrase
Pour chacun des milliers d’échantillons bootstrap, pvclust (1) rééchantillonne les données, (2) les re-regroupe, et (3) pour chaque regroupement enregistre s’il a réapparu. La fréquence de réapparition est la valeur BP ; une correction multi-échelle de celle-ci (rééchantillonnage à plusieurs tailles d’échantillon) est la valeur AU. Les regroupements dont l’AU ≥ 95 % sont considérés comme fortement soutenus par les données.
Les données
Nous utilisons le jeu de données lung fourni avec pvclust — le profil d’expression génique de 916 gènes sur 73 échantillons de tissu pulmonaire (dont 67 tumeurs). C’est le jeu de données sur lequel la méthode a été démontrée, donc c’est le bon pour l’apprendre. Les colonnes sont des échantillons ; les lignes sont des gènes.
library(pvclust)# Load the data that ships with pvclustdata("lung")# A 6-genes × 4-samples corner: rows are genes, columns are sampleshead(lung[, 1:4])
Regrouper les 73 échantillons surchargerait le dendrogramme, alors nous prenons un sous-ensemble aléatoire de 30 échantillons. Nous fixons une graine pour que le sous-ensemble (et tout ce qui en découle) soit reproductible.
library(pvclust)data("lung")set.seed(123)ss <-sample(1:73, 30) # pick 30 of the 73 samples at randomdf <- lung[, ss] # keep all genes, those 30 samplesdim(df) # 916 genes × 30 samples
[1] 916 30
Importantpvclust regroupe les COLONNES — transposez si vous visez les lignes
pvclust() regroupe toujours les colonnes de la matrice que vous lui donnez. Ici les colonnes sont les échantillons que nous voulons grouper, alors nous passons df tel quel. Si vous vouliez plutôt regrouper les gènes (les lignes), vous passeriez t(df) pour transposer d’abord. Cela piège presque tout le monde la première fois — décidez ce que sont vos « objets », et faites-en les colonnes.
Calculer les p-values avec pvclust()
Ce que signifient les arguments
Avant de l’exécuter, voici ce que vous choisissez :
pvclust(data,method.hclust ="average", # linkage rule (as in hclust)method.dist ="correlation", # distance between columnsnboot =1000) # number of bootstrap replications
data — une matrice numérique ou un data frame ; les colonnes sont les objets à regrouper.
method.hclust — la méthode de linkage, passée directement à hclust() : "average" (par défaut), "ward", "complete", "single", et ainsi de suite.
method.dist — la mesure de distance. Pour des données d’expression, la valeur par défaut "correlation" (un moins la corrélation entre échantillons) est le choix naturel ; "euclidean" et "manhattan" sont aussi autorisées.
nboot — combien d’arbres bootstrap construire. Plus de réplications = des p-values plus précises, mais plus de temps. La valeur par défaut est 1000.
pvclust() renvoie un objet qui contient, entre autres, l’arbre hclust des données d’origine ainsi que la p-value AU et BP de chaque branche.
Astucenboot : le curseur vitesse–précision
nboot = 1000 est le réglage précis que vous utiliseriez pour de vrais résultats, mais il est lent. Pour garder cette leçon rapide et reproduire exactement le tutoriel d’origine, nous utilisons nboot = 10 ci-dessous — assez pour voir les mécanismes. Pour tout ce que vous rapporterez, remontez-le à nboot = 1000 (et utilisez parPvclust() pour la vitesse en parallèle — voir Problèmes courants). Avec si peu de réplications, les p-values exactes vont fluctuer, alors lisez le motif, pas le dernier chiffre.
Exécutez-le
Nous regroupons les 30 échantillons (les colonnes) en utilisant la distance de corrélation et le linkage moyen, la combinaison autour de laquelle pvclust est conçu. La graine rend le bootstrap reproductible.
library(pvclust)data("lung")set.seed(123)df <- lung[, sample(1:73, 30)]# Bootstrap p-values for every cluster (nboot = 10 for speed; use 1000 to report)set.seed(123)res.pv <-pvclust(df,method.dist ="cor", # correlation distancemethod.hclust ="average", # average linkagenboot =10)
Lire le dendrogramme : AU et BP à chaque branche
Tracer le résultat dessine le dendrogramme avec les deux p-values affichées à chaque branche, et pvrect() trace un rectangle autour de chaque regroupement que les données soutiennent fortement (AU ≥ 95 % par défaut).
# Dendrogram with AU/BP p-values, then box the strongly-supported clustersplot(res.pv, hang =-1, cex =0.5)pvrect(res.pv)
Comment lire les nombres sur l’arbre. À chaque branche vous voyez :
AU (en rouge, en haut à gauche) — la p-value Approximately Unbiased, en pourcentage.
BP (en vert, en haut à droite) — la Bootstrap Probability, la fréquence brute de réapparition.
étiquettes de regroupement (en gris, le long du bas) — simplement un indice pour chaque nœud interne.
Une branche dont les nombres sont proches de 100 est un regroupement que le bootstrap a continué de trouver — une forte preuve qu’il est réel. Une branche aux valeurs faibles est un regroupement que le rééchantillonnage a rarement reproduit — probablement du bruit. Les rectangles marquent les regroupements dont l’AU ≥ 95 % : ce sont ceux que vous pouvez défendre.
AstuceFiez-vous à l’AU plutôt qu’à la BP
L’AU et la BP estiment la même chose — la reproductibilité d’un regroupement — mais la BP est biaisée : elle tend à être trop conservatrice pour les regroupements qui comptent. L’AU corrige ce biais par rééchantillonnage bootstrap multi-échelle, donc l’AU est la p-value à rapporter et sur laquelle fixer le seuil. Quand elles divergent, croyez l’AU.
Extraire les regroupements significatifs avec pvpick()
Lire les boîtes sur un graphique convient pour un coup d’œil ; pour réellement utiliser les regroupements soutenus, vous les extrayez avec pvpick(). Par défaut il renvoie chaque regroupement dont l’AU ≥ 95 % — les mêmes que ceux encadrés par pvrect() — sous forme de listes d’échantillons membres.
Chaque élément de clusters$clusters est un regroupement significatif — les noms d’échantillons qui vont ensemble avec un fort soutien bootstrap. Ce sont les groupes qui méritent d’être nommés et étudiés ; le reste de l’arbre est une structure que les données n’appuient pas.
Des p-values plus rapides : bootstrap en parallèle
Le réglage honnête — nboot = 1000 — est là où l’attente se manifeste. pvclust fournit une version parallèle, parPvclust(), qui répartit les réplications bootstrap sur les cœurs du CPU. Mêmes arguments, même sortie, plusieurs fois plus rapide :
library(parallel)# A 2-worker cluster (use detectCores() to see what you have)cl <-makeCluster(2, type ="PSOCK")# Parallel pvclust with the accurate nboot = 1000res.pv <-parPvclust(cl, df, nboot =1000)stopCluster(cl) # always release the workers when done
Utilisez iseed = (et non set.seed()) pour rendre une exécution parallèle reproductible, puisque les workers tirent leurs propres flux aléatoires.
Essayez en direct
Exécutez pvclust sur les échantillons lung et encadrez les regroupements fortement soutenus. Essayez de monter nboot à 100 pour des p-values plus stables (cela reste rapide), ou remplacez method.hclust par "ward". Cliquez sur Run.
🟢 Avec un agent IA
Demandez à Prova« le clustering dans mes données est-il statistiquement soutenu ? » — elle exécute pvclust() sur votre propre matrice, lit les p-values AU à chaque branche, vous dit quels regroupements franchissent la barre des 95 %, et vous prévient lorsque vous avez oublié de transposer. The runtime is the judge.Demander à Prova →
Problèmes courants
L’AU et la BP divergent — laquelle croire ?L’AU. La BP (Bootstrap Probability) est la fréquence brute de réapparition et elle est biaisée — généralement trop conservatrice pour les vrais regroupements. L’AU (Approximately Unbiased) applique une correction bootstrap multi-échelle pour supprimer ce biais, alors fixez le seuil et rapportez sur l’AU ≥ 95 %, et traitez la BP comme un nombre secondaire, de vérification.
C’est terriblement lent. Deux leviers. D’abord, nboot est le moteur du coût — nboot = 10 est réservé aux démos ; nboot = 1000 est pour les résultats, et tout l’intervalle entre les deux échange précision contre temps. Ensuite, parallélisez avec parPvclust() sur les cœurs du CPU (voir ci-dessus) — même réponse, divisée par le nombre de workers.
Mes regroupements sont sortis faux / il a regroupé la mauvaise chose.pvclust() regroupe les colonnes. Si vos objets sont dans les lignes (le cas courant pour un data frame ordonné : une ligne par observation), passez t(df) pour transposer d’abord. Un dendrogramme « absurde » est presque toujours une transposition oubliée.
Mes p-values changent à chaque exécution. Le bootstrap est aléatoire. Deux corrections : fixez une graine (set.seed() pour la version en série, iseed = pour parPvclust()), et augmentez nboot — un petit nboot fait sauter les nombres AU/BP un peu partout. Avec nboot = 10, attendez-vous à des fluctuations ; à nboot = 1000 ils se stabilisent.
Questions fréquentes
NoteComment calculer une p-value pour des regroupements en R ?
Utilisez le package pvclust. pvclust(data, method.dist = "cor", method.hclust = "average", nboot = 1000) attache une p-value bootstrap à chaque branche de l’arbre de classification hiérarchique. plot() le résultat pour voir les p-values sur le dendrogramme, pvrect() pour encadrer les regroupements fortement soutenus, et pvpick() pour les extraire. Rappelez-vous qu’il regroupe les colonnes de data.
NoteQuelle est la différence entre AU et BP dans pvclust ?
La BP (Bootstrap Probability) est la fréquence brute à laquelle un regroupement réapparaît à travers les échantillons bootstrap. L’AU (Approximately Unbiased) est une correction bootstrap multi-échelle de la BP qui supprime un biais connu. Elles estiment la même chose, mais l’AU est plus précise et c’est la valeur que vous devriez rapporter et sur laquelle fixer le seuil (AU ≥ 95 %).
Un regroupement est considéré comme fortement soutenu par les données lorsque sa p-value AU est ≥ 95 %. Exécutez pvclust(), puis pvpick(res) renvoie exactement ces regroupements (et pvrect(res) les encadre sur le dendrogramme). Les regroupements aux faibles valeurs d’AU sont probablement des artefacts de votre échantillon particulier, pas une vraie structure.
NotePourquoi pvclust regroupe-t-il les colonnes de mes données ?
Par conception — il a été construit pour la génomique, où les échantillons sont des colonnes et les gènes des lignes, et où l’on veut habituellement regrouper les échantillons. Si vos objets sont plutôt dans les lignes, transposez avec t() avant d’appeler pvclust(). C’est l’erreur de pvclust la plus courante.
NoteCombien de réplications bootstrap (nboot) devrais-je utiliser ?
nboot = 1000 pour tout résultat que vous rapporterez — c’est la valeur par défaut, et pour une bonne raison. Les valeurs plus petites (10, 100) conviennent pour explorer rapidement les mécanismes mais rendent les p-values AU/BP bruitées. Si 1000 est trop lent, gardez la précision et parallélisez avec parPvclust() plutôt que de réduire nboot.
Testez vos connaissances
ImportantExercice : extraire les regroupements significatifs
Exécutez pvclust() sur un sous-ensemble de 30 échantillons de lung avec nboot = 100, puis utilisez pvpick() pour afficher les regroupements qui franchissent la barre AU ≥ 95 %.
# nboot = 100 inside pvclust(), and the extraction function is pvpick()
Conceptuel. Une branche de votre dendrogramme affiche AU = 98 % et BP = 71 %. Le regroupement est-il bien soutenu, et quel nombre rapportez-vous ? (Réponse : Oui, il est bien soutenu — l’AU est ≥ 95 %. Vous rapportez l’AU, parce que la BP est biaisée et que l’AU corrige ce biais ; la faible BP ici est exactement le conservatisme que l’AU corrige.)
Conceptuel. Vous passez un data frame ordonné avec une ligne par observation à pvclust() et l’arbre n’a aucun sens. Qu’est-ce qui a mal tourné ? (Réponse : pvclust regroupe les colonnes, donc il a regroupé vos variables, pas vos observations. Transposez avec t() pour que vos observations deviennent les colonnes.)
Conclusion
Un dendrogramme seul ne vous dit jamais si ses regroupements sont réels. pvclust comble cette lacune : il bootstrappe l’arbre, affiche une p-value AU et BP à chaque branche, et vous permet d’encadrer (pvrect()) et d’extraire (pvpick()) les regroupements que les données soutiennent véritablement — ceux dont l’AU ≥ 95 %. Regroupez le bon axe (les colonnes, alors transposez si nécessaire), utilisez nboot = 1000 pour tout ce que vous rapportez (parallélisé avec parPvclust() quand cela traîne), et fiez-vous à l’AU plutôt qu’à la BP. Avec une p-value attachée, vos regroupements cessent d’être un récit plein d’espoir pour devenir un résultat défendable.
Vous préférez un livre ? Practical Guide to Cluster Analysis in R est disponible en PDF téléchargeable — toutes les leçons de cette série, hors ligne et à vous.
Prouvez que vous savez le faire. Maîtrisez toute la série Analyse de clustering en R — suivez votre parcours, construisez des projets et obtenez un certificat.
@online{2026,
author = {},
title = {P-value en classification hiérarchique avec R (pvclust)},
date = {2026-06-24},
url = {https://www.datanovia.com/learn/machine-learning/clustering/p-value-hierarchical-clustering},
langid = {fr}
}