La matrice de comptage RNA-seq en R : import et contrôle qualité
Là où commence toute analyse RNA-seq — comprenez la matrice de comptage, chargez-la dans un DESeqDataSet, et contrôlez-la avant de tester
Un guide pratique de la matrice de comptage RNA-seq bulk en R. Comprenez ce qu’est une matrice de comptage (gènes × échantillons de comptages de reads bruts), importez vos comptages dans R de deux façons courantes — depuis une table featureCounts/HTSeq avec DESeqDataSetFromMatrix, ou depuis Salmon/kallisto via tximport — appariez-les à une table d’échantillons, et réalisez les contrôles qualité dont toute analyse a besoin : tailles de librairie, distributions de comptages, et filtrage des gènes à faible comptage. Sur le jeu de données airway.
Date de publication
29 juin 2026
Modifié
7 juillet 2026
AstucePoints clés
La matrice de comptage est le point de départ de toute analyse RNA-seq bulk : les lignes sont des gènes, les colonnes sont des échantillons, et chaque valeur est le nombre de reads attribués à ce gène dans cet échantillon.
Utilisez des comptages entiers bruts — jamais des valeurs TPM, FPKM ou normalisées. DESeq2 modélise les comptages et réalise sa propre normalisation en interne.
Importez vos comptages dans R de deux façons courantes : DESeqDataSetFromMatrix() depuis une table featureCounts/HTSeq, ou tximport() → DESeqDataSetFromTximport() depuis des quantifications de transcrits Salmon/kallisto.
Les colonnes de comptage et la table d’échantillons (colData) doivent s’aligner dans le même ordre — le bug de configuration le plus courant.
CQ avant de tester : vérifiez les tailles de librairie (signalez les échantillons à très faible profondeur), inspectez les distributions de comptages, et filtrez les gènes à faible comptage (ils ne portent aucun signal et gonflent les tests multiples).
Introduction
Toute analyse RNA-seq bulk — expression différentielle, PCA, enrichissement — part du même objet : une matrice de comptage. Les outils en amont (l’aligneur et un quantificateur comme featureCounts ou Salmon) ont déjà transformé les reads de séquençage bruts en une table indiquant combien de reads sont tombés sur chaque gène dans chaque échantillon. Votre travail en R commence ici : comprendre cette table, la charger correctement, et la vérifier avant de faire confiance à quoi que ce soit en aval.
Ce guide utilise le jeu de données airway, fourni comme un objet de comptage prêt à l’emploi, de sorte que chaque étape est reproductible — et montre les motifs d’import que vous utiliseriez pour vos propres comptages.
À quoi ressemble une matrice de comptage
airway est un RangedSummarizedExperiment — un conteneur qui regroupe la matrice de comptage (assay) et la table d’échantillons (colData) afin qu’elles ne puissent jamais se désynchroniser. Examinons les deux.
library(airway)data("airway")dim(airway) # genes x samples
[1] 63677 8
assay(airway)[1:5, 1:4] # the count matrix: raw integer counts
Et la table d’échantillons qui s’apparie avec ces colonnes — une ligne par échantillon, dans le même ordre :
# The sample table — one row per column of the matrix, in the SAME order.as.data.frame(colData(airway)[, c("cell", "dex")])
cell dex
SRR1039508 N61311 untrt
SRR1039509 N61311 trt
SRR1039512 N052611 untrt
SRR1039513 N052611 trt
SRR1039516 N080611 untrt
SRR1039517 N080611 trt
SRR1039520 N061011 untrt
SRR1039521 N061011 trt
Trois choses définissent une matrice de comptage valide : les valeurs sont des comptages entiers bruts, les lignes sont des gènes (ici des identifiants Ensembl), et les colonnes sont des échantillons dont l’ordre correspond exactement à la table d’échantillons.
Importer vos propres comptages dans R
airway est pré-empaqueté ; vos données arriveront sous forme de fichiers. Les deux voies courantes :
Depuis une table de comptages (featureCounts, HTSeq, ou tout CSV gènes × échantillons) — lisez-la, séparez les colonnes de comptage des éventuelles colonnes d’annotation, et construisez l’objet avec une table d’échantillons correspondante :
library(DESeq2)counts <-as.matrix(read.csv("counts.csv", row.names =1)) # genes x samplescoldata <-read.csv("samples.csv", row.names =1) # one row per sample# The matrix columns and coldata rows MUST be in the same order:counts <- counts[, rownames(coldata)]dds <-DESeqDataSetFromMatrix(countData = counts,colData = coldata,design =~ condition)
Depuis des quantificateurs de transcrits (Salmon, kallisto) — agrégez les transcrits au niveau des gènes avec tximport, puis transmettez le résultat à DESeq2 :
DESeqDataSetFromMatrix vérifie les noms : si votre colData a des noms de lignes qui ne correspondent pas aux colonnes de comptage, il lève une erreur plutôt que de deviner — un garde-fou utile. Mais il ne peut pas détecter une inversion lorsque la table d’échantillons n’a aucun nom de ligne, car il se fie alors aveuglément à la position des colonnes. Donnez donc toujours des noms de lignes à colData, alignez-les d’abord (counts <- counts[, rownames(coldata)]), et confirmez avec all(colnames(counts) == rownames(coldata)) avant de construire l’objet.
Contrôle qualité avant l’analyse
Quelques vérifications rapides détectent les catastrophes — une librairie ratée, une inversion, un échantillon à faible profondeur — avant qu’elles ne vous coûtent cher.
Tailles de librairie
La taille de librairie est le total de reads alignés par échantillon. Une profondeur très inégale, ou un échantillon bien en dessous des autres, est un signal d’alerte (DESeq2 normalise pour la profondeur, mais une librairie à très faible profondeur porte tout de même peu d’information).
library(ggplot2)libsize <-data.frame(sample =colnames(assay(dds)),millions =colSums(assay(dds)) /1e6,dex = dds$dex)ggplot(libsize, aes(reorder(sample, millions), millions, fill = dex)) +geom_col() +coord_flip() +scale_fill_viridis_d(end =0.85) +labs(x =NULL, y ="Library size (million reads)", fill ="Treatment") +theme_minimal()
Les huit échantillons se situent entre environ 15 et 31 millions de reads — suffisamment réguliers, aucun n’étant relégué bien en dessous des autres. Aucun échantillon ne mérite d’être écarté sur la seule profondeur.
Distributions de comptages
Une boîte à moustaches des comptages transformés en log par échantillon montre si les échantillons sont globalement comparables. Ils devraient se ressembler ; une boîte nettement décalée par rapport aux autres signale un problème.
La plupart des gènes sont à peine détectés — ils ne portent aucune information et alourdissent seulement la charge des tests multiples. Écartez ceux qui n’ont presque aucun read sur l’ensemble des échantillons.
cat("genes before filtering:", nrow(dds), "\n")
genes before filtering: 63677
dds <- dds[rowSums(counts(dds)) >=10, ] # keep genes with >= 10 reads totalcat("genes after filtering: ", nrow(dds), "\n")
genes after filtering: 22369
Le filtre fait passer airway de 63 677 gènes à environ 22 000 — la majeure partie du génome n’est détectée dans aucune expérience donnée, et la retirer rend tout l’aval plus rapide et la correction FDR moins sévère. L’objet est maintenant prêt pour la PCA et le regroupement d’échantillons et l’expression différentielle.
Problèmes fréquents
Colonnes et lignes d’échantillons mal alignées. Si votre table d’échantillons a des noms de lignes, DESeq2 lève une erreur en cas d’incohérence ; le danger silencieux est un colDatasans noms de lignes, où la position des colonnes est suivie aveuglément et où chaque échantillon peut finir mal étiqueté. Nommez toujours les lignes, réordonnez (counts[, rownames(coldata)]), et vérifiez all(colnames(counts) == rownames(coldata)) avant de construire l’objet.
Des valeurs normalisées au lieu de comptages bruts. Les valeurs TPM/FPKM/RPKM et transformées en log cassent le modèle de comptage. DESeq2 a besoin de comptages entiers bruts et normalise en interne. Si vos nombres comportent des décimales, ce ne sont pas des comptages bruts.
Identifiants de gènes stockés dans une colonne. Si votre CSV contient une colonne d’identifiants de gènes, définissez-la comme noms de lignes (read.csv(..., row.names = 1)) — sinon elle est traitée comme un échantillon et as.matrix convertit tout en texte.
Questions fréquentes
NoteQuels comptages DESeq2 attend-il — bruts ou normalisés ?
Des comptages entiers bruts. DESeq2 modélise les comptages avec une loi binomiale négative et estime ses propres facteurs de taille, il doit donc recevoir des entiers non normalisés. Ne lui fournissez jamais de valeurs TPM, FPKM, RPKM ou transformées en log — elles violent les hypothèses du modèle.
NotefeatureCounts ou Salmon — quelle voie d’import ?
Les deux sont standard. featureCounts/HTSeq fournissent une table de comptages gènes × échantillons → DESeqDataSetFromMatrix(). Salmon/kallisto fournissent des estimations par transcrit → agrégez-les au niveau des gènes avec tximport() → DESeqDataSetFromTximport() (cela transmet aussi à DESeq2 des informations d’offset utiles). Utilisez celle que votre pipeline a produite.
NoteQu’est-ce qu’un SummarizedExperiment ?
Un conteneur Bioconductor qui réunit la matrice de comptage (assay), la table par échantillon (colData) et les informations sur les gènes (rowData) dans un seul objet — de sorte que les échantillons et leurs métadonnées ne puissent jamais se désynchroniser. airway en est un ; DESeqDataSet l’étend.
NoteAvec quelle sévérité faut-il filtrer les gènes à faible comptage ?
Légèrement. Une règle courante consiste à conserver les gènes avec ≥ 10 reads au total sur l’ensemble des échantillons (ou ≥ 10 dans au moins quelques échantillons). Le but est seulement d’écarter les gènes quasi indétectables ; le filtrage indépendant de DESeq2 gère la coupe plus fine ensuite. Ne filtrez pas sur le fold change ou la p-value avant de tester.
Testez vos connaissances
ImportantÀ vous de jouer : CQ d’une matrice de comptage à partir de zéro
À partir de assay(airway), calculez la taille de librairie de chaque échantillon en millions, puis indiquez combien de gènes ont zéro comptage dans tous les échantillons. Quelle fraction du génome cela représente-t-il environ ?
AstuceIndice
colSums() donne les tailles de librairie ; rowSums(cm) == 0 repère les gènes entièrement nuls ; mean() de ce vecteur logique donne la fraction.
AstuceSolution
cm <-assay(airway)colSums(cm) /1e6# library sizes (millions)sum(rowSums(cm) ==0) # genes with zero counts everywheremean(rowSums(cm) ==0) # ...as a fraction (~0.47, about half)
Près de la moitié des gènes annotés ne sont jamais détectés dans cette expérience — c’est normal, et c’est exactement pourquoi le filtrage est la première étape.
NoteVérification rapide : quelles valeurs entrent dans DESeq2 ?
A. TPM ou FPKM, car ils sont comparables entre échantillons. B. Des comptages entiers bruts. C. Des comptages transformés en log2.
AstuceAfficher la réponse
B. Des comptages entiers bruts. DESeq2 modélise directement les comptages et normalise en interne ; les valeurs pré-normalisées ou transformées en log violent ses hypothèses.
Conclusion
Vous connaissez maintenant l’objet sur lequel repose toute analyse RNA-seq : une matrice de comptage de comptages entiers bruts, lignes = gènes, colonnes = échantillons, appariée à une table d’échantillons dans l’ordre correspondant. Vous avez vu les deux voies d’import (DESeqDataSetFromMatrix pour les tables de comptages, tximport pour Salmon/kallisto), construit un DESeqDataSet, et réalisé le CQ essentiel — tailles de librairie, distributions de comptages, et filtrage des gènes à faible comptage (ici 63 677 → ~22 000). Les règles pratiques : comptages bruts uniquement, alignez l’ordre des échantillons, et CQ avant de tester. Ensuite, explorez les échantillons avec la PCA et le regroupement, puis lancez l’expression différentielle.
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
Love, M. I., Huber, W., & Anders, S. (2014). Moderated estimation of fold change and dispersion for RNA-seq data with DESeq2. Genome Biology, 15(12), 550.
Soneson, C., Love, M. I., & Robinson, M. D. (2015). Differential analyses for RNA-seq: transcript-level estimates improve gene-level inferences (tximport). F1000Research, 4, 1521.
Himes, B. E., et al. (2014). RNA-Seq transcriptome profiling identifies CRISPLD2 as a glucocorticoid responsive gene in airway smooth muscle cells (le jeu de données airway). PLoS ONE, 9(6), e99625.
@online{2026,
author = {},
title = {La matrice de comptage RNA-seq en R : import et contrôle
qualité},
date = {2026-06-29},
url = {https://www.datanovia.com/learn/bioinformatics/bulk-rna-seq/rna-seq-count-matrix},
langid = {fr}
}