Normalisation Seurat : normaliser, trouver les gènes variables & mettre à l’échelle un jeu de données scRNA-seq

Transformez des comptages bruts en une matrice d’expression comparable et mise à l’échelle — log-normalisez pour la profondeur de séquençage, choisissez les 2000 gènes qui séparent les types cellulaires, et centrez chaque gène avant la réduction de dimension

Un guide pratique pour normaliser des données de RNA-seq single-cell en R avec Seurat. À partir d’un objet Seurat filtré par CQ, log-normalisez les comptages avec NormalizeData pour éliminer les effets de profondeur de séquençage, identifiez les 2000 gènes hautement variables qui portent les différences d’une cellule à l’autre avec FindVariableFeatures (vst), lisez le graphique étiqueté des gènes variables, et mettez les données à l’échelle avec ScaleData pour que chaque gène contribue également à la PCA et au regroupement.

Date de publication

29 juin 2026

Modifié

7 juillet 2026

AstucePoints clés
  • Les comptages bruts ne sont pas comparables d’une cellule à l’autre — une cellule séquencée deux fois plus profondément affiche environ deux fois plus de comptages pour le même gène. La normalisation élimine cet effet de profondeur pour rendre l’expression comparable.
  • NormalizeData() applique une log-normalisation (LogNormalize) : divise chaque comptage par le total de la cellule, met à l’échelle 10 000, puis prend log(1 + x). Le résultat est stocké dans une nouvelle couche data ; les comptages bruts sont conservés.
  • FindVariableFeatures() identifie les gènes hautement variables (HVG) — les gènes qui diffèrent le plus d’une cellule à l’autre. La méthode par défaut vst, avec nfeatures = 2000, conserve les 2000 qui portent le signal biologique.
  • Le graphique des gènes variables est la figure à lire : les principaux HVG de pbmc3k (PPBP, LYZ, S100A9, GNLY, …) sont des marqueurs de types cellulaires — des gènes de plaquettes, de monocytes et de cellules NK qui séparent les populations que vous allez regrouper.
  • ScaleData() centre chaque gène à une moyenne de 0 et le met à l’échelle d’une variance unitaire, pour que quelques gènes fortement exprimés ne dominent pas. Par défaut, il met à l’échelle les 2000 gènes variables — exactement ce dont la PCA a besoin ensuite.

Introduction

Vous disposez d’un objet Seurat propre : 2 638 cellules pbmc3k filtrées par contrôle qualité, des comptages bruts, rien d’autre. Vous ne pouvez pas encore regrouper sur ces comptages. Deux problèmes s’y opposent. D’abord, les cellules ont été séquencées à des profondeurs différentes — une cellule peut avoir 2 400 comptages au total, une autre 4 900 — de sorte que le même gène apparaît plus élevé dans la cellule plus profonde pour une raison purement technique. Ensuite, parmi les ~13 700 gènes, la plupart sont soit éteints, soit exprimés à un niveau plat et peu informatif dans chaque cellule ; seule une minorité diffère réellement entre les types cellulaires, et ce sont ceux-là qui devraient guider l’analyse.

Cette leçon corrige les deux, en trois étapes que tout workflow Seurat exécute avant la réduction de dimension : normaliser les comptages pour rendre les cellules comparables, trouver les gènes variables qui portent le signal, et les mettre à l’échelle pour que chaque gène contribue sur un pied d’égalité. En reprenant la leçon sur le contrôle qualité, nous travaillons sur le même objet pbmc3k pour que le workflow se transfère directement à vos propres données 10x.

Reprendre après le CQ : reconstruire l’objet propre

Chaque bloc de code ici est autonome : il commence donc par recréer l’objet filtré par CQ de la leçon précédente — charger la matrice 10x, construire l’objet Seurat, ajouter percent.mt, et restreindre aux cellules propres. C’est exactement le résultat sur lequel vous avez terminé C2.

library(Seurat)

# Re-establish the QC-filtered object from the previous lesson
pbmc.data <- Read10X("_data/filtered_gene_bc_matrices/hg19")
pbmc <- CreateSeuratObject(pbmc.data, project = "pbmc3k",
                           min.cells = 3, min.features = 200)
pbmc[["percent.mt"]] <- PercentageFeatureSet(pbmc, pattern = "^MT-")
pbmc <- subset(pbmc, subset = nFeature_RNA > 200 & nFeature_RNA < 2500 & percent.mt < 5)
pbmc
An object of class Seurat 
13714 features across 2638 samples within 1 assay 
Active assay: RNA (13714 features, 0 variable features)
 1 layer present: counts

13 714 gènes pour 2 638 cellules, avec une seule couche counts — le point de départ propre. Tout ce qui suit opère sur cet objet.

Normaliser les comptages

Le problème que résout la normalisation est la profondeur de séquençage. Les comptages sont compositionnels : le total d’une cellule est fixé par la profondeur à laquelle elle a été séquencée, non par la biologie, de sorte que deux cellules ayant la même expression réelle mais des profondeurs différentes affichent des comptages bruts différents. Les comparer directement confondrait la profondeur avec le type cellulaire.

NormalizeData() applique la correction standard, la log-normalisation (LogNormalize). Pour chaque cellule, elle divise chaque comptage de gène par le total des comptages de la cellule (éliminant l’effet de profondeur), multiplie par un facteur d’échelle de 10 000 (pour que les nombres tiennent dans une plage commode), et prend le logarithme naturel de un plus cette valeur. L’étape log(1 + x) à la fois apprivoise la longue queue de droite de quelques comptages très élevés et maintient les zéros à zéro.

library(Seurat)
pbmc.data <- Read10X("_data/filtered_gene_bc_matrices/hg19")
pbmc <- CreateSeuratObject(pbmc.data, project = "pbmc3k",
                           min.cells = 3, min.features = 200)
pbmc[["percent.mt"]] <- PercentageFeatureSet(pbmc, pattern = "^MT-")
pbmc <- subset(pbmc, subset = nFeature_RNA > 200 & nFeature_RNA < 2500 & percent.mt < 5)

# Log-normalize: divide by library size, scale to 10,000, log(1 + x)
pbmc <- NormalizeData(pbmc, normalization.method = "LogNormalize", scale.factor = 1e4)

Layers(pbmc[["RNA"]])           # raw "counts" kept; a new "data" layer added
[1] "counts" "data"  

Les valeurs par défaut montrées (LogNormalize, scale.factor = 1e4) sont exactement celles qu’utilise NormalizeData(pbmc), si bien que l’ appel s’écrit généralement sans arguments. Les valeurs normalisées atterrissent dans une nouvelle couche data ; la couche counts brute reste intacte, vous pouvez donc toujours revenir en arrière.

Pour voir ce que la normalisation a réellement fait, comparez un même gène entre des cellules de profondeurs différentes :

library(Seurat)
pbmc.data <- Read10X("_data/filtered_gene_bc_matrices/hg19")
pbmc <- CreateSeuratObject(pbmc.data, project = "pbmc3k",
                           min.cells = 3, min.features = 200)
pbmc[["percent.mt"]] <- PercentageFeatureSet(pbmc, pattern = "^MT-")
pbmc <- subset(pbmc, subset = nFeature_RNA > 200 & nFeature_RNA < 2500 & percent.mt < 5)
pbmc <- NormalizeData(pbmc)

# Library sizes of the first three cells (very different depths)
pbmc$nCount_RNA[1:3]
AAACATACAACCAC-1 AAACATTGAGCTAC-1 AAACATTGATCAGC-1 
            2419             4903             3147 
# Raw vs normalized expression of CD3D (a T-cell gene) in those same cells
LayerData(pbmc, layer = "counts")[ "CD3D", 1:3]
AAACATACAACCAC-1 AAACATTGAGCTAC-1 AAACATTGATCAGC-1 
               4                0               10 
round(LayerData(pbmc, layer = "data")[ "CD3D", 1:3], 3)
AAACATACAACCAC-1 AAACATTGAGCTAC-1 AAACATTGATCAGC-1 
           2.864            0.000            3.490 

Les trois cellules ont été séquencées à 2 419, 4 903 et 3 147 comptages au total. La première cellule a 4 comptages CD3D bruts et la troisième en a 10 — mais après normalisation pour la profondeur, leurs valeurs CD3D sont 2.86 et 3.49 : bien plus proches, parce que le comptage brut plus élevé de la troisième cellule tenait en partie simplement à sa plus grande profondeur. La cellule du milieu n’a pas de CD3D (une cellule non-T) et reste à 0. C’est la normalisation qui fait son travail — placer les cellules sur une échelle comparable avant de les comparer.

Trouver les gènes variables

La plupart des gènes sont sans intérêt pour distinguer les types cellulaires : les gènes de ménage se situent à un niveau similaire partout, et beaucoup de gènes sont à peine détectés. Les gènes qui comptent pour le regroupement sont ceux dont l’expression varie d’une cellule à l’autre — élevée dans une population, faible dans une autre. Ce sont les gènes hautement variables (HVG), et se concentrer sur eux affine le signal biologique tout en réduisant le bruit et le calcul.

FindVariableFeatures() classe les gènes selon leur variabilité après avoir tenu compte du fait que les gènes plus fortement exprimés sont naturellement plus variables. La méthode par défaut vst ajuste cette tendance moyenne–variance, standardise chaque gène par rapport à elle, et les classe selon la variance standardisée. Vous conservez les nfeatures = 2000 premiers — la valeur par défaut de Seurat, un compromis bien éprouvé : assez de gènes pour capturer chaque type cellulaire, assez peu pour garder la PCA en aval rapide et ciblée.

library(Seurat)
pbmc.data <- Read10X("_data/filtered_gene_bc_matrices/hg19")
pbmc <- CreateSeuratObject(pbmc.data, project = "pbmc3k",
                           min.cells = 3, min.features = 200)
pbmc[["percent.mt"]] <- PercentageFeatureSet(pbmc, pattern = "^MT-")
pbmc <- subset(pbmc, subset = nFeature_RNA > 200 & nFeature_RNA < 2500 & percent.mt < 5)
pbmc <- NormalizeData(pbmc)

# Identify the 2000 most variable genes (vst method)
pbmc <- FindVariableFeatures(pbmc, selection.method = "vst", nfeatures = 2000)

length(VariableFeatures(pbmc))          # 2000 genes selected
[1] 2000
head(VariableFeatures(pbmc), 10)        # the 10 most variable
 [1] "PPBP"   "LYZ"    "S100A9" "IGLL5"  "GNLY"   "FTL"    "PF4"    "FTH1"  
 [9] "GNG11"  "S100A8"

Seurat a sélectionné 2 000 gènes variables et les classe selon la variance standardisée. Les 10 premiers sont PPBP, LYZ, S100A9, IGLL5, GNLY, FTL, PF4, FTH1, GNG11, S100A8 — et ils ne sont pas aléatoires. PPBP, PF4 et GNG11 sont des marqueurs de plaquettes/mégacaryocytes ; LYZ, S100A9, S100A8, FTL et FTH1 sont des gènes monocytaires/myéloïdes ; GNLY marque les cellules NK et cytotoxiques ; IGLL5 est un gène de lymphocytes B. Chacun est activé dans une seule population restreinte et silencieux ailleurs — exactement le motif de forte variance que la sélection des HVG est conçue pour capter. Les gènes variables sont le signal des types cellulaires.

Lire le graphique des gènes variables

VariableFeaturePlot() montre chaque gène sous forme de point — l’expression moyenne sur l’axe des x, la variance standardisée sur l’axe des y — avec les 2000 gènes sélectionnés en rouge. LabelPoints() ajoute les noms des 10 premiers.

library(Seurat)
pbmc.data <- Read10X("_data/filtered_gene_bc_matrices/hg19")
pbmc <- CreateSeuratObject(pbmc.data, project = "pbmc3k",
                           min.cells = 3, min.features = 200)
pbmc[["percent.mt"]] <- PercentageFeatureSet(pbmc, pattern = "^MT-")
pbmc <- subset(pbmc, subset = nFeature_RNA > 200 & nFeature_RNA < 2500 & percent.mt < 5)
pbmc <- NormalizeData(pbmc)
pbmc <- FindVariableFeatures(pbmc, selection.method = "vst", nfeatures = 2000)

top10 <- head(VariableFeatures(pbmc), 10)
plot1 <- VariableFeaturePlot(pbmc)
LabelPoints(plot = plot1, points = top10, repel = TRUE)

A scatter plot of every pbmc3k gene with average expression on a log x-axis and standardized variance on the y-axis. The 11,714 non-variable genes form a dense black band of low variance near the bottom; the 2000 selected variable genes are red and spread upward. Ten genes are labelled far above the rest — PPBP highest at a standardized variance near 11, then S100A9, LYZ, IGLL5, GNLY, FTL, PF4, FTH1, GNG11 and S100A8 — the high-variance cell-type markers.

Lisez-le de bas en haut. La bande noire le long du bas représente les 11 714 gènes non variables — variance faible et plate, sans utilité pour séparer les cellules. Les points rouges qui s’élèvent au-dessus sont les 2 000 gènes variables, et la poignée étiquetée tout en haut (PPBP le plus haut, variance standardisée ≈ 11) sont les gènes qui diffèrent le plus. L’expression moyenne d’un gène (axe des x) ne décide pas de son rang : PPBP est globalement peu exprimé mais extrêmement variable car il est très élevé dans les quelques plaquettes et nul partout ailleurs, tandis que les gènes de ménage abondants se situent bas sur l’axe des y. C’est la variance, non l’abondance, qui marque un gène comme informatif — c’est exactement ce sur quoi les étapes suivantes vont s’appuyer.

Mettre les données à l’échelle

Il reste une étape avant la réduction de dimension. La PCA trouve les directions de plus grande variance, donc sans correction, une poignée de gènes fortement exprimés (comme FTL ou FTH1, aux plus grandes valeurs brutes) domineraient chaque composante simplement parce que leurs nombres sont les plus grands — non parce qu’ils sont les plus informatifs sur le plan biologique. ScaleData() empêche cela en standardisant chaque gène : il soustrait la moyenne du gène (le centre à 0) et divise par son écart-type (le met à l’échelle d’une variance unitaire), pour que chaque gène entre dans la PCA sur un pied d’égalité.

library(Seurat)
pbmc.data <- Read10X("_data/filtered_gene_bc_matrices/hg19")
pbmc <- CreateSeuratObject(pbmc.data, project = "pbmc3k",
                           min.cells = 3, min.features = 200)
pbmc[["percent.mt"]] <- PercentageFeatureSet(pbmc, pattern = "^MT-")
pbmc <- subset(pbmc, subset = nFeature_RNA > 200 & nFeature_RNA < 2500 & percent.mt < 5)
pbmc <- NormalizeData(pbmc)
pbmc <- FindVariableFeatures(pbmc, selection.method = "vst", nfeatures = 2000)

# Center and scale each gene (default: the variable features only)
pbmc <- ScaleData(pbmc)

dim(LayerData(pbmc, layer = "scale.data"))     # genes x cells in the scaled matrix
[1] 2000 2638

La matrice mise à l’échelle est de 2 000 × 2 638 — par défaut, ScaleData() ne met à l’échelle que les gènes variables, ce qui est tout ce dont la PCA a besoin et garde les choses rapides. Si vous voulez mettre à l’échelle chaque gène (pour une heatmap de gènes quelconques, par exemple), passez features = rownames(pbmc) et il met à l’échelle les 13 714 gènes. Le résultat va dans une troisième couche, scale.data, aux côtés de counts et data. Notez que les valeurs mises à l’échelle servent à la PCA et à la visualisation, non à l’ expression différentielle — celle-ci utilise la couche data (log-normalisée).

Votre objet porte désormais trois représentations des mêmes cellules : les counts bruts, les data log-normalisées, et les scale.data centrées et mises à l’échelle sur les 2000 gènes variables. Il est prêt pour la réduction de dimension linéaire, le regroupement et l’UMAP.

Une note sur SCTransform

NormalizeData → FindVariableFeatures → ScaleData est le workflow classique en trois étapes et celui que la plupart des tutoriels enseignent. Seurat propose aussi SCTransform(), une fonction unique qui remplace les trois : elle modélise les comptages avec une loi binomiale négative régularisée et renvoie en un seul appel des valeurs normalisées, à variance stabilisée, ainsi que les gènes variables, gérant souvent les différences de profondeur et le bruit technique avec plus d’élégance. Elle est plus lourde et un peu plus une boîte noire, c’est pourquoi cette série s’en tient à la voie explicite en trois étapes — elle rend chaque opération visible et c’est ce qu’utilise le tutoriel pbmc3k canonique. Une fois les trois étapes claires, passer à SCTransform() plus tard ne change qu’une ligne.

Problèmes fréquents

ScaleData() avertit que certains gènes ne figurent pas dans les données mises à l’échelle. Par conception, ScaleData() ne met à l’échelle que les gènes variables, de sorte qu’un appel en aval (une heatmap, un FeaturePlot de la couche mise à l’échelle) pour un gène hors du top 2000 ne trouve rien. Soit vous ajoutez ce gène aux gènes que vous mettez à l’échelle, soit vous mettez tout à l’échelle d’emblée avec ScaleData(pbmc, features = rownames(pbmc)).

Exécuter les étapes dans le mauvais ordre. Le pipeline dépend de l’ordre : ScaleData() opère sur la couche data normalisée (qui est vide tant que vous n’avez pas exécuté NormalizeData()), et la PCA s’attend à ce que les gènes variables soient définis. Exécutez NormalizeData → FindVariableFeatures → ScaleData ; lancer ScaleData() juste après le CQ met à l’échelle des comptages bruts et donne des composantes dénuées de sens. (FindVariableFeatures(vst) lit lui-même la couche counts, c’est donc l’étape de mise à l’échelle — et non la sélection des HVG — qui impose de normaliser d’abord.)

S’attendre à une liste de gènes différente. Avec les mêmes données et les valeurs par défaut (vst, nfeatures = 2000), la liste des HVG est déterministe — vous devriez obtenir PPBP, LYZ, S100A9, … à chaque fois. Un top-10 différent signifie généralement une normalisation différente, un nfeatures différent, ou que le filtrage CQ a modifié les cellules en entrée.

Questions fréquentes

NormalizeData() applique par défaut une log-normalisation (LogNormalize) : elle divise le comptage de chaque gène par le total des comptages de la cellule, multiplie par un facteur d’échelle de 10 000, et prend log(1 + x). Cela élimine les différences de profondeur de séquençage entre cellules et stocke le résultat dans une nouvelle couche data, laissant la couche counts brute intacte.

La valeur par défaut de Seurat est nfeatures = 2000, qui fonctionne bien pour la plupart des jeux de données, dont pbmc3k — assez de gènes pour capturer chaque type cellulaire sans ralentir la PCA en aval. Vous pouvez l’augmenter (3000–5000) pour un tissu très hétérogène avec de nombreuses populations subtiles, ou la baisser pour un échantillon simple, mais 2000 est un bon point de départ.

Les gènes hautement variables (HVG) sont les gènes dont l’expression diffère le plus d’une cellule à l’autre après prise en compte de leur niveau moyen. Ils portent le signal biologique qui sépare les types cellulaires — dans pbmc3k, les principaux HVG sont des marqueurs de types cellulaires comme PPBP (plaquettes), LYZ (monocytes) et GNLY (cellules NK). Restreindre la réduction de dimension à ces gènes affine la structure et réduit le bruit et le calcul.

Par défaut, ScaleData() ne met à l’échelle que les gènes variables — sur pbmc3k, c’est une matrice 2000 × 2638, ce qui est tout ce dont la PCA a besoin. Passez features = rownames(object) pour centrer et mettre à l’échelle chaque gène à la place, par exemple lorsque vous voulez une heatmap de gènes hors de l’ensemble variable.

LogNormalize (via NormalizeData) est la correction de profondeur classique suivie d’une transformation logarithmique, exécutée dans le cadre du workflow en trois étapes NormalizeData → FindVariableFeatures → ScaleData. SCTransform() remplace les trois par un seul modèle binomial négatif régularisé qui normalise, stabilise la variance et sélectionne les gènes variables en une fois — souvent plus robuste au bruit technique, mais plus lourd et moins transparent. Les deux alimentent les mêmes étapes de PCA/regroupement.

Testez vos connaissances

À partir de l’objet pbmc3k filtré par CQ, log-normalisez les comptages, trouvez les 2000 premiers gènes variables avec la méthode vst, et indiquez combien des 20 premiers gènes variables sont mitochondriaux (noms de gènes commençant par MT-). Puis mettez les données à l’échelle et confirmez les dimensions de la matrice mise à l’échelle.

Après FindVariableFeatures(), head(VariableFeatures(pbmc), 20) donne les 20 premiers ; grep("^MT-", ...) repère les mitochondriaux. dim(LayerData(pbmc, layer = "scale.data")) donne les dimensions de la matrice mise à l’échelle.

library(Seurat)
pbmc.data <- Read10X("_data/filtered_gene_bc_matrices/hg19")
pbmc <- CreateSeuratObject(pbmc.data, project = "pbmc3k",
                           min.cells = 3, min.features = 200)
pbmc[["percent.mt"]] <- PercentageFeatureSet(pbmc, pattern = "^MT-")
pbmc <- subset(pbmc, subset = nFeature_RNA > 200 & nFeature_RNA < 2500 & percent.mt < 5)

pbmc <- NormalizeData(pbmc)
pbmc <- FindVariableFeatures(pbmc, selection.method = "vst", nfeatures = 2000)

top20 <- head(VariableFeatures(pbmc), 20)
grep("^MT-", top20, value = TRUE)        # character(0): none of the top 20 are mitochondrial

pbmc <- ScaleData(pbmc)
dim(LayerData(pbmc, layer = "scale.data"))   # 2000 x 2638

Aucun des 20 premiers gènes variables n’est mitochondrial — ce sont des marqueurs de types cellulaires (PPBP, LYZ, S100A9, …), non les gènes MT- sur lesquels vous avez filtré. La matrice mise à l’échelle est de 2000 × 2638 : les 2000 gènes variables pour les 2638 cellules propres.

A. Ce sont les gènes les plus fortement exprimés, ils portent donc le plus de comptages. B. Ils diffèrent le plus d’une cellule à l’autre, ils portent donc le signal qui sépare les types cellulaires. C. Ce sont les gènes mitochondriaux et ribosomaux utilisés pour le contrôle qualité.

B. Les gènes variables sont les gènes dont l’expression varie le plus d’une cellule à l’autre (après prise en compte de leur niveau moyen). Cette variation d’une cellule à l’autre est le signal biologique qui distingue les types cellulaires — l’abondance (A) ne rend pas un gène informatif, et les gènes de CQ (C) sont filtrés ou régressés, non utilisés pour définir la structure.

Conclusion

Trois étapes transforment une matrice de comptage propre en l’entrée qu’attend la réduction de dimension. Vous avez log-normalisé avec NormalizeData() pour que des cellules de profondeurs différentes deviennent comparables, utilisé FindVariableFeatures() pour sélectionner les 2000 gènes qui diffèrent réellement entre cellules — dans pbmc3k, les marqueurs de types cellulaires PPBP, LYZ, S100A9 et les autres — et les avez mis à l’échelle avec ScaleData() pour qu’aucun gène à forte expression ne domine la PCA. La logique durable : normaliser pour effacer la profondeur technique, se concentrer sur les gènes qui portent le signal, et les placer sur un pied d’égalité. L’objet contient désormais des vues brute, normalisée et mise à l’échelle des mêmes cellules, prêtes à être regroupées.

Leçons connexes

🟢 Avec un agent IA

Demandez à Prova « comment normaliser et trouver les gènes variables pour mon propre objet Seurat ? » — elle répond avec du code R que vous pouvez exécuter sur votre propre matrice, exécute NormalizeData/FindVariableFeatures/ScaleData, et vous aide à lire le graphique des gènes variables de vos données. The runtime is the judge. Demander à Prova →

Cette page vous a-t-elle été utile ?

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.

Partager cette pageXLinkedInRedditHN
Note

Cette leçon est reproductible : chaque figure et chaque nombre ont été produits par le code montré — copiez n’importe quel bloc et exécutez-le pour les reproduire. The runtime is the judge.

Références

  • Hao, Y., et al. (2021). Integrated analysis of multimodal single-cell data (Seurat v4). Cell, 184(13), 3573–3587.
  • Stuart, T., et al. (2019). Comprehensive integration of single-cell data. Cell, 177(7), 1888–1902.
  • Hafemeister, C., & Satija, R. (2019). Normalization and variance stabilization of single-cell RNA-seq data using regularized negative binomial regression. Genome Biology, 20(1), 296.
  • 10x Genomics. 3k PBMCs from a Healthy Donor — la matrice gène–code-barres filtrée pbmc3k canonique (Cell Ranger 1.1.0).

Réutilisation

Citation

BibTeX
@online{2026,
  author = {},
  title = {Normalisation Seurat : normaliser, trouver les gènes
    variables \& mettre à l’échelle un jeu de données scRNA-seq},
  date = {2026-06-29},
  url = {https://www.datanovia.com/learn/bioinformatics/single-cell/scrnaseq-normalization-hvg.html},
  langid = {fr}
}
Veuillez citer ce travail comme suit :
“Normalisation Seurat : normaliser, trouver les gènes variables & mettre à l’échelle un jeu de données scRNA-seq.” 2026. June 29. https://www.datanovia.com/learn/bioinformatics/single-cell/scrnaseq-normalization-hvg.html.