GRanges et GRangesList : intervalles génomiques en R avec Bioconductor

Représentez, filtrez et recoupez des plages génomiques avec le package GenomicRanges

Représentez des intervalles génomiques en R avec le package Bioconductor GenomicRanges — construisez des objets GRanges et GRangesList, attachez des métadonnées, trouvez et comptez les chevauchements, et résumez la couverture avec Rle et Views. La structure de données d’intervalle fondamentale sur laquelle repose le reste de Bioconductor.

Date de publication

8 juillet 2026

Modifié

9 juillet 2026

AstucePoints clés
  • Un objet GRanges (genomic ranges) stocke un ensemble d’intervalles sur un génome : pour chacun un chromosome (seqnames), une plage début–fin et un brin. C’est la structure de données que parle le reste de Bioconductor.
  • Attachez n’importe quelle donnée par intervalle — scores, noms de gènes, p-values — sous forme de colonnes de métadonnées avec mcols(), puis filtrez l’objet comme un vecteur et chaque colonne suit.
  • Un GRangesList regroupe plusieurs GRanges sous un seul objet — la forme naturelle pour des exons regroupés par gène ou des pics regroupés par échantillon.
  • L’opération de fond consiste à trouver les chevauchements : findOverlaps(), countOverlaps() et le raccourci %over% répondent à « lesquels de ces intervalles touchent ceux-là ? » — la base de l’annotation de pics et du comptage de lectures.
  • La couverture transforme un tas d’intervalles en une piste de profondeur par base, stockée de façon compacte sous forme d’un Rle (run-length encoding) ; les Views permettent de relire des résumés dans n’importe quelle région.

Introduction

Presque tout en génomique est un intervalle sur un chromosome : un gène s’étend d’une coordonnée à une autre, une lecture de séquençage s’aligne sur une portion de bases, un pic ChIP-seq marque une région liée, un variant se situe à une position unique. Les questions récurrentes portent toutes sur ces intervalles — quels pics tombent à l’intérieur d’un gène ? combien de lectures couvrent cet exon ? où deux jeux d’annotations concordent-ils ?

Vous pourriez stocker des intervalles dans un simple data frame avec des colonnes chrom, start, end, mais alors chaque requête de chevauchement devient une comparaison bricolée à la main et chaque sous-ensemble risque de désaligner les coordonnées de leurs métadonnées. GenomicRanges — le package Bioconductor conçu exactement pour cela — vous offre un conteneur sur mesure, l’objet GRanges, ainsi que des opérations rapides et correctes sur celui-ci. C’est la fondation sur laquelle reposent les packages d’analyse : un DESeqDataSet, un SummarizedExperiment, une annotation TxDb portent tous un GRanges à l’intérieur. Apprenez-le une fois et le versant à l’échelle du génome de Bioconductor cesse de ressembler à une comptabilité improvisée.

Cette leçon construit des objets GRanges et GRangesList à partir de zéro, y attache des métadonnées, les filtre, trouve les chevauchements et calcule la couverture — le tout sur de petits intervalles synthétiques que vous pouvez afficher et lire, de sorte que chaque résultat est visible sur la page et reproductible sur votre machine. Consultez la page du package GenomicRanges pour la référence complète.

Construire un GRanges

Un objet GRanges représente un ensemble d’intervalles génomiques. Construisez-en un avec le constructeur GRanges() : donnez-lui les noms de chromosomes (seqnames), un IRanges de coordonnées début/fin, le brin, et — facultativement — toute colonne par intervalle (ici un score). IRanges() est le type de plages entières du package compagnon IRanges ; GRanges y ajoute le chromosome et le brin.

library(GenomicRanges)

gr <- GRanges(
  seqnames = "chr1",
  ranges   = IRanges(start = c(5, 10, 25), end = c(15, 20, 40)),
  strand   = c("+", "+", "-"),
  score    = c(10L, 25L, 7L)
)
gr
GRanges object with 3 ranges and 1 metadata column:
      seqnames    ranges strand |     score
         <Rle> <IRanges>  <Rle> | <integer>
  [1]     chr1      5-15      + |        10
  [2]     chr1     10-20      + |        25
  [3]     chr1     25-40      - |         7
  -------
  seqinfo: 1 sequence from an unspecified genome; no seqlengths

Lisez l’affichage de haut en bas. L’en-tête indique 3 ranges and 1 metadata column : trois intervalles, chacun avec un score. Les colonnes à gauche du | sont l’intervalle lui-même — seqnames (tous chr1), ranges (le début–fin que vous avez fourni), strand — et les colonnes à droite du | sont vos métadonnées. La ligne entre chevrons nomme le type de chaque colonne (<Rle>, <IRanges>, <integer>) ; <Rle> est l’encodage compressé que GenomicRanges utilise pour seqnames et strand, abordé à la fin. Le pied de page seqinfo enregistre les chromosomes — ici un seul, sans longueur déclarée.

Accédez à n’importe quel composant avec son accesseur. Chacun renvoie un vecteur simple sur lequel vous pouvez calculer :

library(GenomicRanges)
gr <- GRanges("chr1", IRanges(c(5, 10, 25), c(15, 20, 40)),
              strand = c("+", "+", "-"), score = c(10L, 25L, 7L))

seqnames(gr)   # chromosome of each interval
factor-Rle of length 3 with 1 run
  Lengths:    3
  Values : chr1
Levels(1): chr1
start(gr)      # 5 10 25
[1]  5 10 25
end(gr)        # 15 20 40
[1] 15 20 40
width(gr)      # end - start + 1  ->  11 11 16
[1] 11 11 16
strand(gr)     # + + -
factor-Rle of length 3 with 2 runs
  Lengths: 2 1
  Values : + -
Levels(3): + - *

Notez que width vaut end - start + 1 — GenomicRanges utilise des coordonnées à base 1, inclusives (la même convention qu’Ensembl et que les formats SAM/VCF), donc une plage de 5 à 15 fait 11 bases de large, et non 10.

Attacher et utiliser des colonnes de métadonnées

Les colonnes à droite du | sont des colonnes de métadonnées — des données arbitraires par intervalle — et vous accédez à toute la table avec mcols(). Ajoutez une colonne en affectant à mcols(gr)$name ; elle s’aligne avec les intervalles position par position.

library(GenomicRanges)
gr <- GRanges("chr1", IRanges(c(5, 10, 25), c(15, 20, 40)),
              strand = c("+", "+", "-"), score = c(10L, 25L, 7L))

mcols(gr)                        # the metadata table: one column so far (score)
DataFrame with 3 rows and 1 column
      score
  <integer>
1        10
2        25
3         7
mcols(gr)$gene <- c("GENA", "GENB", "GENC")   # add a gene label per interval
gr
GRanges object with 3 ranges and 2 metadata columns:
      seqnames    ranges strand |     score        gene
         <Rle> <IRanges>  <Rle> | <integer> <character>
  [1]     chr1      5-15      + |        10        GENA
  [2]     chr1     10-20      + |        25        GENB
  [3]     chr1     25-40      - |         7        GENC
  -------
  seqinfo: 1 sequence from an unspecified genome; no seqlengths

L’objet porte désormais 2 colonnes de métadonnées, score et gene. C’est pourquoi un GRanges surpasse trois vecteurs épars : les coordonnées et leur annotation vivent dans un même objet et se déplacent ensemble.

Cela porte ses fruits quand vous filtrez. Indexez un GRanges comme un vecteur — avec des positions, ou avec un test logique sur n’importe quelle colonne — et les plages ainsi que chaque colonne de métadonnées sont filtrées d’un seul geste :

library(GenomicRanges)
gr <- GRanges("chr1", IRanges(c(5, 10, 25), c(15, 20, 40)),
              strand = c("+", "+", "-"), score = c(10L, 25L, 7L),
              gene = c("GENA", "GENB", "GENC"))

gr[strand(gr) == "+"]            # keep plus-strand intervals
GRanges object with 2 ranges and 2 metadata columns:
      seqnames    ranges strand |     score        gene
         <Rle> <IRanges>  <Rle> | <integer> <character>
  [1]     chr1      5-15      + |        10        GENA
  [2]     chr1     10-20      + |        25        GENB
  -------
  seqinfo: 1 sequence from an unspecified genome; no seqlengths
gr[mcols(gr)$score > 8]          # keep intervals scoring above 8
GRanges object with 2 ranges and 2 metadata columns:
      seqnames    ranges strand |     score        gene
         <Rle> <IRanges>  <Rle> | <integer> <character>
  [1]     chr1      5-15      + |        10        GENA
  [2]     chr1     10-20      + |        25        GENB
  -------
  seqinfo: 1 sequence from an unspecified genome; no seqlengths

Le premier conserve les deux intervalles du brin plus ; le second écarte GENC (score 7). Vous n’avez jamais touché à la colonne gene, et pourtant elle a suivi correctement — la garantie qui rend le conteneur digne de confiance.

Transformer les plages

GenomicRanges fournit une arithmétique d’intervalles qui respecte le brin. Trois fonctions que vous utiliserez constamment : shift() fait glisser un intervalle, resize() fixe sa largeur à partir d’une ancre fixe, et flank() saisit la région adjacente (une façon courante de construire des fenêtres de promoteur en amont du début d’un gène).

library(GenomicRanges)
gr <- GRanges("chr1", IRanges(c(5, 10, 25), c(15, 20, 40)),
              strand = c("+", "+", "-"), score = c(10L, 25L, 7L))

shift(gr, 100)                   # move every interval 100 bp to the right
GRanges object with 3 ranges and 1 metadata column:
      seqnames    ranges strand |     score
         <Rle> <IRanges>  <Rle> | <integer>
  [1]     chr1   105-115      + |        10
  [2]     chr1   110-120      + |        25
  [3]     chr1   125-140      - |         7
  -------
  seqinfo: 1 sequence from an unspecified genome; no seqlengths
resize(gr, width = 5)            # first 5 bp, anchored at each interval's START
GRanges object with 3 ranges and 1 metadata column:
      seqnames    ranges strand |     score
         <Rle> <IRanges>  <Rle> | <integer>
  [1]     chr1       5-9      + |        10
  [2]     chr1     10-14      + |        25
  [3]     chr1     36-40      - |         7
  -------
  seqinfo: 1 sequence from an unspecified genome; no seqlengths
flank(gr, width = 3)             # the 3 bp immediately upstream of each interval
GRanges object with 3 ranges and 1 metadata column:
      seqnames    ranges strand |     score
         <Rle> <IRanges>  <Rle> | <integer>
  [1]     chr1       2-4      + |        10
  [2]     chr1       7-9      + |        25
  [3]     chr1     41-43      - |         7
  -------
  seqinfo: 1 sequence from an unspecified genome; no seqlengths

resize() et flank() tiennent compte du brin : « start » et « upstream » désignent l’extrémité 5′, donc pour le brin moins GENC (25–40) l’ancre est la coordonnée de droite, et non de gauche. C’est exactement ce que vous voulez pour des caractéristiques génomiques — un promoteur se trouve en amont dans le sens de la transcription, quel que soit le brin.

Regrouper des intervalles : GRangesList

Un GRangesList regroupe plusieurs objets GRanges en un seul — la représentation naturelle lorsque les intervalles appartiennent à une hiérarchie. Le cas d’école est celui des exons regroupés par gène (ou par transcrit) : chaque élément de la liste est l’ensemble des exons d’un gène.

library(GenomicRanges)

exons_geneA <- GRanges("chr1", IRanges(c(100, 200, 300), c(150, 250, 360)), strand = "+")
exons_geneB <- GRanges("chr1", IRanges(c(500, 700), c(600, 800)), strand = "-")

grl <- GRangesList(geneA = exons_geneA, geneB = exons_geneB)
grl
GRangesList object of length 2:
$geneA
GRanges object with 3 ranges and 0 metadata columns:
      seqnames    ranges strand
         <Rle> <IRanges>  <Rle>
  [1]     chr1   100-150      +
  [2]     chr1   200-250      +
  [3]     chr1   300-360      +
  -------
  seqinfo: 1 sequence from an unspecified genome; no seqlengths

$geneB
GRanges object with 2 ranges and 0 metadata columns:
      seqnames    ranges strand
         <Rle> <IRanges>  <Rle>
  [1]     chr1   500-600      -
  [2]     chr1   700-800      -
  -------
  seqinfo: 1 sequence from an unspecified genome; no seqlengths

grl a deux éléments — geneA avec trois exons, geneB avec deux. Interrogez la liste elle-même, ou extrayez un élément pour récupérer un GRanges ordinaire :

library(GenomicRanges)
exons_geneA <- GRanges("chr1", IRanges(c(100, 200, 300), c(150, 250, 360)), strand = "+")
exons_geneB <- GRanges("chr1", IRanges(c(500, 700), c(600, 800)), strand = "-")
grl <- GRangesList(geneA = exons_geneA, geneB = exons_geneB)

length(grl)          # number of genes: 2
[1] 2
elementNROWS(grl)    # exons per gene: geneA 3, geneB 2
geneA geneB 
    3     2 
grl[["geneA"]]       # one element -> a plain GRanges
GRanges object with 3 ranges and 0 metadata columns:
      seqnames    ranges strand
         <Rle> <IRanges>  <Rle>
  [1]     chr1   100-150      +
  [2]     chr1   200-250      +
  [3]     chr1   300-360      +
  -------
  seqinfo: 1 sequence from an unspecified genome; no seqlengths
range(grl)           # the full span (min start to max end) of each gene
GRangesList object of length 2:
$geneA
GRanges object with 1 range and 0 metadata columns:
      seqnames    ranges strand
         <Rle> <IRanges>  <Rle>
  [1]     chr1   100-360      +
  -------
  seqinfo: 1 sequence from an unspecified genome; no seqlengths

$geneB
GRanges object with 1 range and 0 metadata columns:
      seqnames    ranges strand
         <Rle> <IRanges>  <Rle>
  [1]     chr1   500-800      -
  -------
  seqinfo: 1 sequence from an unspecified genome; no seqlengths

elementNROWS() compte les intervalles à l’intérieur de chaque élément, et range() réduit les exons de chaque gène à son étendue génomique complète (100–360 pour geneA) — une seule ligne pour transformer des modèles d’exons en corps de gènes.

Trouver les chevauchements

L’opération de génomique la plus courante consiste à demander quels intervalles d’un ensemble chevauchent lesquels d’un autre — annoter des pics par les gènes qu’ils touchent, compter des lectures par exon, croiser deux jeux de caractéristiques. Mettons en place un petit exemple : quatre pics et trois gènes sur chr1.

library(GenomicRanges)

peaks <- GRanges("chr1", IRanges(c(8, 30, 120, 900), c(18, 45, 140, 950)))
genes <- GRanges("chr1", IRanges(c(1, 25, 500), c(20, 60, 800)),
                 strand = "+", gene = c("GENA", "GENB", "GENC"))

findOverlaps(query, subject) renvoie un objet Hits : une carte à deux colonnes indiquant quel intervalle de query chevauche quel intervalle de subject, par position.

library(GenomicRanges)
peaks <- GRanges("chr1", IRanges(c(8, 30, 120, 900), c(18, 45, 140, 950)))
genes <- GRanges("chr1", IRanges(c(1, 25, 500), c(20, 60, 800)),
                 strand = "+", gene = c("GENA", "GENB", "GENC"))

hits <- findOverlaps(query = peaks, subject = genes)
hits
Hits object with 2 hits and 0 metadata columns:
      queryHits subjectHits
      <integer>   <integer>
  [1]         1           1
  [2]         2           2
  -------
  queryLength: 4 / subjectLength: 3
queryHits(hits)      # peaks that overlapped:   1 2
[1] 1 2
subjectHits(hits)    # the genes they hit:      1 2
[1] 1 2

Lisez-le par paires : le pic 1 chevauche le gène 1, le pic 2 chevauche le gène 2. Les pics 3 (120–140) et 4 (900–950) ne correspondent à aucun gène, ils n’apparaissent donc jamais. queryHits()/subjectHits() fournissent les deux colonnes sous forme de vecteurs d’entiers avec lesquels vous pouvez indexer — p. ex. genes$gene[subjectHits(hits)] étiquette chaque pic chevauchant avec son gène.

Lorsque vous n’avez besoin que d’un compte ou d’un oui/non plutôt que de l’appariement complet, deux raccourcis sont plus légers :

library(GenomicRanges)
peaks <- GRanges("chr1", IRanges(c(8, 30, 120, 900), c(18, 45, 140, 950)))
genes <- GRanges("chr1", IRanges(c(1, 25, 500), c(20, 60, 800)),
                 strand = "+", gene = c("GENA", "GENB", "GENC"))

countOverlaps(peaks, genes)      # how many genes each peak hits: 1 1 0 0
[1] 1 1 0 0
peaks %over% genes               # logical: does each peak hit ANY gene?
[1]  TRUE  TRUE FALSE FALSE
peaks[peaks %over% genes]        # keep only the peaks that overlap something
GRanges object with 2 ranges and 0 metadata columns:
      seqnames    ranges strand
         <Rle> <IRanges>  <Rle>
  [1]     chr1      8-18      *
  [2]     chr1     30-45      *
  -------
  seqinfo: 1 sequence from an unspecified genome; no seqlengths

countOverlaps() est la primitive de comptage de lectures — remplacez « peaks » par des lectures alignées et « genes » par des exons et vous obtenez des comptes par gène. %over% renvoie un vecteur logique, donc peaks[peaks %over% genes] filtre en une ligne. Pour conserver plutôt le côté annoté — les gènes touchés par au moins un pic, avec leurs métadonnées — utilisez subsetByOverlaps() :

library(GenomicRanges)
peaks <- GRanges("chr1", IRanges(c(8, 30, 120, 900), c(18, 45, 140, 950)))
genes <- GRanges("chr1", IRanges(c(1, 25, 500), c(20, 60, 800)),
                 strand = "+", gene = c("GENA", "GENB", "GENC"))

subsetByOverlaps(genes, peaks)   # genes covered by >= 1 peak, columns intact
GRanges object with 2 ranges and 1 metadata column:
      seqnames    ranges strand |        gene
         <Rle> <IRanges>  <Rle> | <character>
  [1]     chr1      1-20      + |        GENA
  [2]     chr1     25-60      + |        GENB
  -------
  seqinfo: 1 sequence from an unspecified genome; no seqlengths

Par défaut, nonfindOverlaps() et consorts ignorent le brin, de sorte qu’un pic du brin plus peut chevaucher un gène du brin moins. C’est généralement ce que vous voulez pour des questions basées sur la position. Quand le brin compte (p. ex. le comptage de lectures RNA-seq orientées), passez ignore.strand = FALSE ; deux intervalles ne se chevauchent alors que s’ils partagent aussi un brin. Soyez toujours explicite sur ce que vous entendez.

Couverture : profondeur par base

La couverture répond à « combien d’intervalles couvrent chaque position ? » — la piste de profondeur derrière chaque empilement de lectures. coverage() prend un GRanges de lectures et renvoie, par chromosome, la profondeur à chaque base.

library(GenomicRanges)

reads <- GRanges("chr1", IRanges(start = c(1, 5, 10, 10), width = 8))
cov <- coverage(reads)
cov
RleList of length 1
$chr1
integer-Rle of length 17 with 5 runs
  Lengths: 4 4 1 3 5
  Values : 1 2 1 3 2
as.numeric(cov$chr1)             # depth at each position, expanded
 [1] 1 1 1 1 2 2 2 2 1 3 3 3 2 2 2 2 2

Les quatre lectures s’étendent sur les positions 1–17. En lisant le vecteur développé : les positions 1–4 sont couvertes une fois, 5–8 deux fois, la position 9 une fois, les positions 10–12 par trois lectures (deux lectures commencent à 10 par-dessus une troisième), et 13–17 deux fois. Cette profondeur par base est ce qu’un navigateur de génome dessine sous forme de piste de couverture.

L’affichage compact — integer-Rle of length 17 with 5 runs — est la clé qui explique pourquoi cela passe à l’échelle de génomes entiers.

Rle : codage par plages (run-length encoding)

La couverture sur un chromosome est un vecteur long de milliards de positions, mais il ne change de valeur qu’aux frontières des intervalles — de longues portions se répètent. Un Rle (run-length encoding) stocke un tel vecteur sous forme de ses valeurs distinctes plus la longueur de plage de chaque valeur, au lieu de chaque élément. Une piste de 3 milliards de bases devient quelques millions de plages.

library(GenomicRanges)

r <- Rle(c(0, 0, 0, 2, 2, 2, 2, 1, 1, 0, 0))
r                    # 11 values stored as 4 runs
numeric-Rle of length 11 with 4 runs
  Lengths: 3 4 2 2
  Values : 0 2 1 0
runValue(r)          # the distinct values:  0 2 1 0
[1] 0 2 1 0
runLength(r)         # how long each runs:    3 4 2 2
[1] 3 4 2 2
as.numeric(r)        # expand back to the full vector
 [1] 0 0 0 2 2 2 2 1 1 0 0

Onze positions se compressent en quatre plages ; une véritable piste de couverture se compresse bien davantage. Un Rle se comporte comme un vecteur normal — l’arithmétique (mean(r), sum(r)) et la comparaison élément par élément fonctionnent toutes — tout en restant compressé, ce qui est la manière dont GenomicRanges manipule des signaux à l’échelle du génome sans épuiser la mémoire.

Views : lire des résumés d’une région

Un objet Views vous permet d’examiner des fenêtres précises d’un Rle (ou de tout vecteur long) sans copier les données — chaque vue n’est qu’un début/fin dans le sujet sous-jacent. Résumez plusieurs régions à la fois avec viewMeans(), viewMaxs() et leurs semblables — le motif derrière « la couverture moyenne par exon ».

library(GenomicRanges)
r <- Rle(c(0, 0, 0, 2, 2, 2, 2, 1, 1, 0, 0))

v <- Views(r, start = c(1, 7), end = c(6, 11))
v
Views on a 11-length Rle subject

views:
    start end width
[1]     1   6     6 [0 0 0 2 2 2]
[2]     7  11     5 [2 1 1 0 0]
viewMeans(v)         # mean signal in each window: 1.0 0.8
[1] 1.0 0.8
viewMaxs(v)          # peak signal in each window: 2 2
[1] 2 2

Deux fenêtres, deux résumés — calculés directement à partir du Rle compressé. Appliquez la même idée à une piste de couverture avec vos exons comme fenêtres et vous obtenez des statistiques de couverture par caractéristique en un seul appel.

Problèmes fréquents

« cannot coerce » ou une erreur de brin lors de la construction d’un GRanges. strand n’accepte que +, - ou * (non spécifié) — tout le reste provoque une erreur. Donnez une seule valeur à recycler sur tous les intervalles (strand = "+") ou un vecteur de la même longueur que les plages. De même, chaque colonne de métadonnées doit correspondre au nombre d’intervalles.

Les chevauchements reviennent vides alors que vous attendez des correspondances. Deux pièges ici : vos intervalles peuvent se trouver sur des chromosomes différents (un chevauchement exige les mêmes seqnames), ou vous avez fixé ignore.strand = FALSE et les brins ne concordent pas. Affichez les deux objets et vérifiez les colonnes seqnames et strand avant de supposer que les plages sont fausses.

Un GRanges affiche seqinfo: … no seqlengths. Ce n’est qu’une note — vous n’avez jamais déclaré les longueurs de chromosomes. C’est sans conséquence pour le travail de chevauchement et de couverture ; cela ne compte que lorsqu’une opération a besoin des bornes du chromosome (comme rogner les plages à l’extrémité du chromosome), ce que vous pouvez définir plus tard avec seqlengths().

Questions fréquentes

Un GRanges (du package Bioconductor GenomicRanges) est un conteneur pour intervalles génomiques : chaque intervalle porte un chromosome (seqnames), une plage début–fin et un brin, plus un nombre quelconque de colonnes de métadonnées (scores, noms de gènes, …). C’est la structure de données standard pour représenter gènes, lectures, pics et variants dans Bioconductor.

Un GRanges est un ensemble plat d’intervalles. Un GRangesList regroupe plusieurs objets GRanges sous un seul conteneur — un élément de liste par groupe. L’usage canonique, ce sont les exons regroupés par gène : chaque élément contient les exons d’un seul gène, et les opérations au niveau de la liste comme range() ou elementNROWS() agissent par gène.

Utilisez findOverlaps(query, subject) pour l’appariement complet (un objet Hits), countOverlaps() pour un compte par intervalle de query, ou x %over% y pour un vecteur TRUE/FALSE avec lequel filtrer. subsetByOverlaps(x, y) renvoie les éléments de x qui chevauchent y, métadonnées intactes.

À base 1 et inclusives, comme Ensembl, GFF et VCF — une plage de 5 à 15 fait 11 bases de large (width = end - start + 1). Cela diffère des fichiers BED et BAM, qui sont à base 0 semi-ouverts ; des importateurs comme rtracklayer::import() convertissent pour vous les coordonnées BED vers la convention à base 1.

Un Rle (run-length encoding) stocke un long vecteur sous forme de ses valeurs distinctes plus la longueur de plage de chaque valeur. Une piste de couverture à l’échelle d’un génome ne change de valeur qu’aux bords des intervalles, elle se compresse donc en une poignée de plages — permettant à GenomicRanges de conserver et de calculer un signal par base sur tout un chromosome sans stocker chaque position.

Testez vos connaissances

En utilisant les objets peaks et genes de la section sur les chevauchements, construisez un vecteur de caractères qui étiquette chaque pic chevauchant avec le nom de gene qu’il touche. (Les pics qui ne touchent rien ne doivent pas apparaître.)

findOverlaps() vous donne queryHits() (quel pic) et subjectHits() (quel gène). Utilisez subjectHits() pour indexer genes$gene.

library(GenomicRanges)
peaks <- GRanges("chr1", IRanges(c(8, 30, 120, 900), c(18, 45, 140, 950)))
genes <- GRanges("chr1", IRanges(c(1, 25, 500), c(20, 60, 800)),
                 strand = "+", gene = c("GENA", "GENB", "GENC"))

hits <- findOverlaps(peaks, genes)
labels <- genes$gene[subjectHits(hits)]
labels                          # "GENA" "GENB"

# tie each label back to its peak:
data.frame(peak = queryHits(hits), gene = labels)

subjectHits(hits) (1 2) indexe genes$gene, donnant le gène touché par chaque pic chevauchant ; en l’appariant avec queryHits(hits), on voit le pic 1 → GENA et le pic 2 → GENB.

A. 10 B. 11 C. 20

B — 11. GenomicRanges utilise des coordonnées à base 1, inclusives, donc width = end - start + 1 = 20 - 10 + 1 = 11. Cela déroute quiconque vient des coordonnées BED/BAM à base 0 semi-ouvertes, où la même étendue vaudrait 10.

Conclusion

GRanges est l’objet d’intervalle sur lequel repose le versant à l’échelle du génome de Bioconductor : un chromosome, une plage et un brin par intervalle, plus des colonnes de métadonnées qui se filtrent au même rythme que les coordonnées. Vous en avez construit un avec GRanges(), y avez accédé avec start()/end()/width()/strand() et mcols(), l’avez filtré comme un vecteur, et avez transformé des intervalles avec shift()/resize()/flank() qui tiennent compte du brin. Vous avez regroupé des intervalles dans un GRangesList (exons par gène), répondu à la question de fond avec findOverlaps()/countOverlaps()/%over%, et résumé le signal avec coverage(), Rle et Views. Les règles pratiques : les coordonnées sont à base 1 inclusives, les chevauchements ignorent le brin par défaut, et la couverture est stockée en codage par plages de sorte qu’elle passe à l’échelle de génomes entiers. Chaque conteneur d’analyse que vous rencontrerez ensuite — SummarizedExperiment, DESeqDataSet, objets d’annotation TxDb — porte ces plages à l’intérieur.

Leçons connexes

  • Le conteneur SummarizedExperiment — l’objet sur lequel DESeq2 et les outils single-cell reposent ; son slot rowRanges est un GRanges, cette leçon est donc la pièce qui se trouve en dessous. · Formats de fichiers en bio-informatique — d’où viennent les intervalles (BED, GFF, BAM) et en quoi leurs conventions de coordonnées diffèrent.
  • Où cela s’inscrit : Données génomiques en R — la série complète (GRanges, visualisation de pistes génomiques et contrôle qualité des lectures). · Bio-informatique — le pilier : RNA-seq, single-cell et workflows omiques reproductibles.
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 objet et chaque nombre de cette page a été produit par le code montré — copiez n’importe quel bloc et exécutez-le pour les reproduire. The runtime is the judge.

Références

  • Lawrence, M., Huber, W., Pagès, H., Aboyoun, P., Carlson, M., Gentleman, R., Morgan, M. T., & Carey, V. J. (2013). Software for computing and annotating genomic ranges. PLoS Computational Biology, 9(8), e1003118.
  • Morgan, M., Obenchain, V., Lang, M., Thompson, R., & Pagès, H. GenomicRanges: Representation and manipulation of genomic intervals. Bioconductorpage du package.

Réutilisation

Citation

BibTeX
@online{2026,
  author = {},
  title = {GRanges et GRangesList : intervalles génomiques en R avec
    Bioconductor},
  date = {2026-07-08},
  url = {https://www.datanovia.com/learn/bioinformatics/genomics/granges-and-granges-list},
  langid = {fr}
}
Veuillez citer ce travail comme suit :
“GRanges et GRangesList : intervalles génomiques en R avec Bioconductor.” 2026. July 8. https://www.datanovia.com/learn/bioinformatics/genomics/granges-and-granges-list.