All in One View
Content from Organisation des données avec des feuilles de calcul
Last updated on 2026-11-07 | Edit this page
Estimated time: 60 minutes
Overview
Questions
- Comment organiser des données tabulaires ?
Objectives
- Découvrez les feuilles de calcul, leurs points forts et leurs points faibles.
- Comment mettre en forme les données dans des feuilles de calcul pour une utilisation efficace des données ?
- Apprenez à reconnaître les erreurs courantes dans les feuilles de calcul et comment les corriger.
- Organisez vos données selon les principes des données ordonnées.
- Apprenez à utiliser des formats de feuilles de calcul textuelles tels que les formats séparés par des virgules (CSV) ou par des tabulations (TSV).
Cet épisode est basé sur la leçon Data Analysis and Visualisation in R for Ecologists de Data Carpentries.
Logiciels de feuilles de calcul
Question
- Quels sont les principes de base pour utiliser des feuilles de calcul afin d’organiser efficacement les données ?
Objectif
- Décrivez les bonnes pratiques pour organiser les données afin que les ordinateurs puissent tirer le meilleur parti des jeux de données.
Point clé
- Une bonne organisation des données est le fondement de tout projet de recherche.
Une bonne organisation des données est le fondement de votre projet de recherche. La plupart des chercheurs disposent de données ou effectuent leur saisie dans des feuilles de calcul. Les logiciels de feuilles de calcul sont des interfaces graphiques très utiles pour concevoir des tableaux de données et gérer des fonctions de contrôle de la qualité des données très basiques. Voir également Broman and Woo (2018).
Plan de la feuille de calcul
Les feuilles de calcul sont adaptées à l’entrée de données. C’est pourquoi nous avons beaucoup de données dans des feuilles de calcul. Une grande partie de votre temps en tant que chercheur sera consacrée à cette étape de « manipulation des données ». Ce n’est pas le plus plaisant, mais c’est nécessaire. Nous vous apprendrons comment concevoir l’organisation des données ainsi que quelques pratiques pour une manipulation des données plus efficace.
Ce que cette leçon ne vous enseignera pas
- Comment effectuer des statistiques dans une feuille de calcul
- Comment réaliser des graphiques dans une feuille de calcul
- Comment écrire du code dans des logiciels de feuilles de calcul
Si vous souhaitez faire cela, une bonne référence est Head First Excel, publié par O’Reilly.
Pourquoi n’enseignons-nous pas l’analyse de données dans des feuilles de calcul ?
L’analyse de données dans des feuilles de calcul nécessite généralement beaucoup de travail manuel. Si vous souhaitez modifier un paramètre ou effectuer une analyse avec un nouveau jeu de données, vous devez généralement tout refaire manuellement. (Il est bien sûr possible de créer des macros, mais voir le point suivant.)
Il est également difficile de retracer ou de reproduire des analyses statistiques ou de graphiques réalisées dans des logiciels de feuilles de calcul lorsque l’on souhaite revenir sur son travail ou que quelqu’un demande des détails sur son analyse.
De nombreux logiciels de feuilles de calcul sont disponibles. Comme la plupart des participants utilisent Excel comme logiciel de feuille de calcul principal, cette leçon s’appuiera sur des exemples Excel. Un autre logiciel de feuille de calcul gratuit utilisable est LibreOffice. Les commandes peuvent légèrement différer d’un programme à l’autre, mais le principe général reste le même.
Les logiciels de feuilles de calcul couvrent bon nombre des tâches que nous devons être capables d’accomplir en tant que chercheurs. Nous pouvons les utiliser pour :
- Saisie de données
- Organisation des données
- Sélection et tri de données
- Statistiques
- Graphiques
Les logiciels de feuilles de calcul utilisent des tableaux pour représenter et afficher des données. Les données formatées sous forme de tableaux constituent également le thème principal de ce chapitre, et nous verrons comment organiser les données en tableaux de manière standardisée afin de garantir une analyse ultérieure efficace.
Défi : Discutez des points suivants avec votre voisin
- Avez-vous utilisé des feuilles de calcul, dans vos recherches, vos cours ou à la maison ?
- Quel type d’opérations effectuez-vous dans des feuilles de calcul ?
- Pour quelles tâches pensez-vous que les feuilles de calcul sont adaptées ?
- Avez-vous déjà fait quelque chose par erreur dans un programme de feuille de calcul qui vous a frustré ou déprimé ?
Problèmes liés aux feuilles de calcul
Les feuilles de calcul sont adaptées à la saisie de données, mais en réalité, nous avons tendance à utiliser les logiciels de feuilles de calcul pour bien plus que cela. Nous les employons pour créer des tableaux de données destinés à des publications, pour générer des statistiques de synthèse et pour réaliser des figures.
Générer des tableaux pour des publications dans une feuille de calcul n’est pas optimal : souvent, lors de la mise en forme d’un tableau de données pour une publication, nous présentons des statistiques de synthèse clés d’une manière qui n’est pas vraiment destinée à être lue comme des données, et cela implique souvent un formatage spécial (fusion de cellules, création de bordures, embellissement). Nous vous conseillons d’effectuer ce type d’opération au sein de votre logiciel de traitement de texte.
Les deux dernières applications, la génération de statistiques et de figures, doivent être utilisées avec prudence : en raison de la nature graphique et par glisser-déposer des programmes de feuilles de calcul, il peut être très difficile, voire impossible, de reproduire vos étapes (et encore moins de suivre celles de quelqu’un d’autre), surtout si vos statistiques ou vos figures nécessitent des calculs plus complexes. De plus, lors de calculs dans une feuille de calcul, il est facile d’appliquer par erreur une formule légèrement différente à plusieurs cellules adjacentes. Lors de l’utilisation d’un programme statistique basé sur une ligne de commande comme R ou SAS, il est pratiquement impossible d’appliquer un calcul à une observation de votre jeu de données mais pas à une autre, à moins de le faire intentionnellement.
Utilisation des feuilles de calcul pour la saisie et le nettoyage des données
Dans cette leçon, nous supposerons que vous utilisez très probablement Excel comme programme de feuilles de calcul principal — il en existe d’autres (gnumeric, Calc d’OpenOffice), et leurs fonctionnalités sont similaires, mais Excel semble être le programme le plus utilisé par les biologistes et les chercheurs en biomédecine.
Dans cette leçon, nous allons aborder :
- Mise en forme des tableaux de données dans des feuilles de calcul
- Problèmes de mise en forme
- Exportation de données
Mise en forme des tableaux de données dans des feuilles de calcul
Questions
- Comment mettre en forme les données dans des feuilles de calcul pour une utilisation efficace des données ?
Objectifs
Décrire les bonnes pratiques de saisie et de mise en forme des données dans des feuilles de calcul.
Appliquez les bonnes pratiques pour organiser les variables et les observations dans une feuille de calcul.
Points clés
Ne modifiez jamais vos données brutes. Effectuez toujours une copie avant d’apporter toute modification.
Consignez dans un fichier texte brut toutes les étapes que vous suivez pour nettoyer vos données.
Organisez vos données selon les principes des données ordonnées.
L’erreur la plus courante consiste à traiter les logiciels de feuilles de calcul comme des cahiers de laboratoire, c’est-à-dire à s’appuyer sur le contexte, des notes en marge, la disposition spatiale des données et des champs pour transmettre des informations. En tant qu’êtres humains, nous pouvons (généralement) interpréter ces éléments, mais les ordinateurs ne perçoivent pas l’information de la même manière et, à moins d’expliquer à l’ordinateur ce que chaque élément signifie (ce qui peut s’avérer difficile !), celui-ci ne pourra pas comprendre comment nos données s’articulent.
Grâce à la puissance des ordinateurs, nous pouvons gérer et analyser des données de manière bien plus efficace et rapide, mais pour exploiter cette puissance, nous devons préparer nos données afin que l’ordinateur puisse les comprendre (et les ordinateurs sont très littéraux).
C’est pourquoi il est extrêmement important de préparer des tableaux bien structurés dès le départ, avant même de commencer à saisir les données de votre toute première expérience préliminaire. L’organisation des données est le fondement de votre projet de recherche. Elle peut faciliter ou compliquer le travail avec vos données tout au long de l’analyse ; il vaut donc la peine d’y réfléchir lors de la saisie des données ou de la mise en place de l’expérience. Vous pouvez organiser vos données de différentes manières dans les feuilles de calcul, mais certains de ces choix peuvent limiter votre capacité à travailler avec les données dans d’autres programmes, ou compliquer leur utilisation par vous-même dans six mois ou par un collaborateur.
Note : les meilleures mises en page et les meilleurs formats (ainsi que les logiciels et les interfaces) pour la saisie et l’analyse des données peuvent différer. Il est important d’en tenir compte et, idéalement, d’automatiser la conversion de l’un à l’autre.
Suivi de vos analyses
Lorsque vous travaillez avec des feuilles de calcul, pendant le nettoyage ou l’analyse des données, il est très facile de vous retrouver avec une feuille de calcul très différente de celle avec laquelle vous avez commencé. Pour pouvoir reproduire vos analyses ou comprendre ce que vous avez fait lorsqu’un évaluateur ou un enseignant demande une analyse différente, vous devriez
créez un nouveau fichier contenant vos données nettoyées ou analysées. Ne modifiez pas le jeu de données d’origine, sinon vous ne saurez jamais par où vous avez commencé !
Gardez une trace des étapes que vous avez franchies lors du nettoyage ou de l’analyse. Vous devez suivre ces étapes comme vous le feriez pour toute étape d’une expérience. Nous vous recommandons de le faire dans un fichier texte brut stocké dans le même dossier que le fichier de données.
Voici un exemple de configuration de feuille de calcul :

Mettez ces principes en pratique dès aujourd’hui lors de vos exercices.
Bien que la gestion des versions ne fasse pas partie du programme de ce cours, vous pouvez consulter la leçon de Carpentries sur ‘Git’ pour apprendre à maintenir le contrôle de version de vos données. Consultez également cet article de blog pour un tutoriel rapide ou Perez-Riverol et al. (2016) pour un cas d’utilisation davantage axé sur la recherche.
Structurer les données dans des feuilles de calcul
Les règles fondamentales de l’utilisation des logiciels de feuilles de calcul pour les données :
- Placez toutes vos variables dans des colonnes — ce que vous mesurez, comme « poids » ou « température ».
- Placez chaque observation dans sa propre ligne.
- Ne combinez pas plusieurs informations dans une seule cellule. Parfois, cela semble n’être qu’une seule chose, mais demandez-vous si c’est la seule façon dont vous souhaiteriez pouvoir utiliser ou trier ces données.
- Laissez les données brutes brutes — ne les modifiez pas !
- Exportez les données nettoyées dans un format textuel tel que le format CSV (valeurs séparées par des virgules). Cela garantit que n’importe qui puisse utiliser les données, et est requis par la plupart des dépôts de données.
Par exemple, nous disposons de données concernant des patients ayant consulté plusieurs hôpitaux à Bruxelles, en Belgique. Ils ont noté la date de la visite, l’hôpital, le sexe des patients, leur poids et leur groupe sanguin.
Si nous devions suivre les données de la manière suivante :

le problème est que les groupes ABO et Rhésus se trouvent dans la
même colonne de type Blood. Ainsi, s’ils voulaient examiner
toutes les observations du groupe A ou analyser les distributions de
poids par groupe ABO, cela serait délicat avec cette configuration de
données. Si, au lieu de cela, nous plaçons les groupes ABO et Rhésus
dans des colonnes différentes, vous voyez que ce serait bien plus
simple.

Une règle importante lors de la création d’une feuille de données est que les colonnes sont utilisées pour les variables et les lignes sont utilisées pour les observations :
- les colonnes sont des variables
- les lignes sont des observations
- les cellules sont des valeurs individuelles
Défi : Nous allons prendre un jeu de données mal structuré et décrire comment nous le nettoierions.
Téléchargez un jeu de données mal structuré en cliquant sur ce lien.
Ouvrez les données dans un programme de feuilles de calcul.
Vous pouvez voir qu’il y a deux onglets. Les données contiennent diverses variables cliniques enregistrées dans différents hôpitaux de Bruxelles lors de la première et de la deuxième vague de COVID-19 en 2020. Comme vous pouvez le voir, les données ont été enregistrées de manière différente lors des vagues de mars et de novembre. Vous êtes désormais la personne responsable de ce projet et vous souhaitez pouvoir commencer à analyser les données.
Avec la personne à vos côtés, identifiez ce qui ne va pas dans cette feuille de calcul. Discutez également des étapes que vous devriez suivre pour nettoyer les onglets des première et deuxième vagues, et pour les réunir toutes dans une seule feuille de calcul.
Important : N’oubliez pas notre premier conseil : créez un nouveau fichier (ou un nouvel onglet) pour les données nettoyées et ne modifiez jamais vos données originales (brutes).
Une fois que vous aurez effectué cet exercice, nous discuterons en groupe de ce qui ne fonctionnait pas dans ces données et de la manière dont vous les corrigeriez.
Défi : Une fois les données nettoyées, répondez aux questions suivantes :
- Combien d’hommes et de femmes ont participé à l’étude ?
- Combien d’échantillons de chacun des groupes sanguins A, AB et B ont été testés ?
- Comme ci-dessus, mais en ignorant les échantillons contaminés ?
- Combien de sujets Rhesus + et - ont été testés ?
- Combien de donneurs universels (O-) ont été testés ?
- Quel est le poids moyen des hommes AB ?
- Combien d’échantillons ont été testés dans les différents hôpitaux ?
Une excellente référence, notamment en ce qui concerne la programmation R, est l’article Tidy Data Wickham (2014).
Erreurs courantes dans les feuilles de calcul
Questions
- Quels sont les défis courants liés au formatage des données dans des feuilles de calcul et comment peut-on les éviter ?
Objectifs
- Reconnaître et résoudre les problèmes courants de mise en forme des feuilles de calcul.
Points clés
- Évitez d’utiliser plusieurs tableaux au sein d’une seule feuille de calcul.
- Évitez de répartir les données sur plusieurs onglets.
- Enregistrez les zéros comme des zéros.
- Utilisez une valeur nulle appropriée pour enregistrer les données manquantes.
- N’utilisez pas de mise en forme pour transmettre des informations ou pour embellir votre feuille de calcul.
- Placez les commentaires dans une colonne distincte.
- Notez les unités dans les en-têtes de colonnes.
- N’incluez qu’une seule information par cellule.
- Évitez les espaces, les chiffres et les caractères spéciaux dans les en-têtes de colonnes.
- Évitez les caractères spéciaux dans vos données.
- Enregistrez les métadonnées dans un fichier texte brut distinct.
Il existe quelques erreurs potentielles auxquelles il convient de prêter attention, tant dans vos propres données que dans celles de vos collaborateurs ou provenant d’Internet. Si vous êtes conscient de ces erreurs et de leur impact négatif possible sur l’analyse ultérieure des données et l’interprétation des résultats, cela pourrait vous motiver, vous et les membres de votre projet, à tenter de les éviter. Apporter de légers ajustements à la manière dont vous formatez vos données dans des feuilles de calcul peut avoir un impact considérable sur l’efficacité et la fiabilité lors du nettoyage et de l’analyse des données.
- Utilisation de plusieurs tableaux
- Utilisation de plusieurs onglets
- Ne pas renseigner les zéros
- Utilisation de valeurs nulles problématiques
- Utiliser la mise en forme pour transmettre des informations
- Utiliser la mise en forme pour embellir la feuille de données
- Placer des commentaires ou des unités dans des cellules
- Saisir plus d’une information dans une cellule
- Utilisation de noms de champs problématiques
- Utilisation de caractères spéciaux dans les données
- Inclusion de métadonnées dans un tableau de données
Utilisation de plusieurs tableaux
Une stratégie courante consiste à créer plusieurs tableaux de données au sein d’une seule feuille de calcul. Cela confonde l’ordinateur, alors ne faites pas cela ! Lorsque vous créez plusieurs tableaux dans une seule feuille de calcul, vous établissez des associations erronées entre les éléments pour l’ordinateur, lequel considère chaque ligne comme une observation. Vous risquez également d’utiliser le même nom de champ à plusieurs endroits, ce qui rendra plus difficile le nettoyage de vos données pour obtenir une forme utilisable. L’exemple ci-dessous illustre ce problème :

Dans l’exemple ci-dessus, l’ordinateur verra (par exemple) la ligne 4 et supposera que toutes les colonnes A-AF se réfèrent au même échantillon. Cette ligne représente en réalité quatre échantillons distincts (l’échantillon 1 pour chacune des quatre dates de prélèvement différentes — le 29 mai, le 12 juin, le 19 juin et le 26 juin), ainsi que certaines statistiques de synthèse calculées (une moyenne (avr) et l’erreur-type de mesure (SEM)) pour deux de ces échantillons. Les autres lignes sont tout aussi problématiques.
Utilisation de plusieurs onglets
Mais qu’en est-il des onglets du classeur ? Cela semble être un moyen simple d’organiser les données, n’est-ce pas ? Eh bien, oui et non. Lorsque vous créez des onglets supplémentaires, vous ne permettez pas à l’ordinateur de percevoir les liens qui existent dans les données (vous devez introduire des fonctions spécifiques à l’application de feuille de calcul ou du scriptage pour garantir ce lien). Disons, par exemple, que vous créez un onglet distinct pour chaque jour où vous effectuez une mesure.
Ce n’est pas une bonne pratique pour deux raisons :
vous êtes plus susceptible d’introduire par inadvertance des incohérences dans vos données si, à chaque mesure, vous commencez à enregistrer les données dans une nouvelle onglet, et
même si vous parvenez à éviter toute incohérence, vous ajouterez une étape supplémentaire avant d’analyser les données, car vous devrez les réunir dans un seul tableau. Vous devrez indiquer explicitement à l’ordinateur comment combiner les onglets et, si ceux-ci sont formatés de manière incohérente, vous pourriez même devoir le faire manuellement.
La prochaine fois que vous saisissez des données et que vous souhaitez créer un autre onglet ou un autre tableau, demandez-vous si vous pourriez éviter d’ajouter cet onglet en ajoutant une autre colonne à votre feuille de calcul d’origine. Nous avons utilisé plusieurs onglets dans notre exemple de fichier de données désordonné, mais vous avez maintenant vu comment vous pouvez réorganiser vos données pour les regrouper entre les onglets.
Votre feuille de données peut devenir très longue au fil de l’expérience. Cela rend la saisie des données plus difficile si vous ne voyez pas vos en-têtes en haut de la feuille de calcul. Mais ne répétez pas votre ligne d’en-tête. Celles-ci peuvent facilement se confondre avec les données, ce qui posera problème par la suite. Au lieu de cela, vous pouvez geler les en-têtes de colonne afin qu’elles restent visibles, même lorsque votre feuille de calcul comporte de nombreuses lignes.
Ne pas renseigner les zéros
Il se peut que, lorsque vous mesurez quelque chose, la valeur soit généralement zéro, par exemple le nombre de fois où un lapin est observé lors de l’enquête. Pourquoi s’embêter à saisir le chiffre zéro dans cette colonne, alors qu’il s’agit pour la plupart de zéros ?
Cependant, il existe une différence entre un zéro et une cellule vide dans une feuille de calcul. Pour l’ordinateur, un zéro est en réalité une donnée. Vous l’avez mesuré ou compté. Une cellule vide signifie qu’elle n’a pas été mesurée et que l’ordinateur l’interprétera comme une valeur inconnue (également appelée valeur nulle ou manquante).
Les feuilles de calcul ou les programmes statistiques interpréteront probablement à tort les cellules vides que vous souhaitez considérer comme des zéros. En ne saisissant pas la valeur de votre observation, vous demandez à votre ordinateur de représenter ces données comme inconnues ou manquantes (nulles). Cela peut poser problème pour les calculs ou les analyses ultérieurs. Par exemple, la moyenne d’un ensemble de nombres comprenant une seule valeur nulle est toujours nulle (car l’ordinateur ne peut pas deviner la valeur des observations manquantes). C’est pourquoi il est très important de consigner les zéros comme des zéros et les données réellement manquantes comme des valeurs nulles.
Utilisation de valeurs nulles problématiques
Exemple : utiliser -999 ou d’autres valeurs numériques (ou zéro) pour représenter des données manquantes.
Solutions :
Il existe plusieurs raisons pour lesquelles les valeurs nulles sont représentées différemment au sein d’un jeu de données. Parfois, des valeurs nulles confuses sont enregistrées automatiquement par le dispositif de mesure. Dans ce cas, il n’y a pas grand-chose que l’on puisse faire, mais cela peut être traité lors du nettoyage des données avec un outil comme OpenRefine avant l’analyse. D’autres fois, des valeurs nulles différentes sont utilisées pour indiquer différentes raisons pour lesquelles les données manquent. Il s’agit d’informations importantes à recueillir, mais cela revient en réalité à utiliser une seule colonne pour enregistrer deux informations. Comme pour l’utilisation du formatage pour transmettre des informations, il serait judicieux ici de créer une nouvelle colonne telle que ‘data_missing’ et d’utiliser cette colonne pour enregistrer les différentes raisons.
Quelle qu’en soit la raison, il est problématique que des données inconnues ou manquantes soient enregistrées sous la forme de -999, 999 ou 0.
De nombreux logiciels statistiques ne reconnaîtront pas que ces valeurs sont destinées à représenter des valeurs manquantes (nulles). La manière dont ces valeurs sont interprétées dépendra du logiciel que vous utilisez pour analyser vos données. Il est essentiel d’utiliser un indicateur de valeur nulle clairement défini et cohérent.
Les cellules vides (dans la plupart des applications) et NA (pour R) sont de bons choix. White et al. (2013) présente dans son article des choix appropriés pour indiquer les valeurs manquantes dans différentes applications logicielles :

Utilisation de la mise en forme pour transmettre des informations
Exemple : mise en évidence de cellules, de lignes ou de colonnes à exclure d’une analyse, laisser des lignes vides pour indiquer des séparations dans les données.

Solution : créer un nouveau champ pour coder les données à exclure.

Utiliser la mise en forme pour embellir la feuille de données
Exemple : fusion de cellules.
Solution : Si vous n’y prenez pas garde, le formatage d’une feuille de calcul pour en améliorer l’aspect esthétique peut compromettre la capacité de votre ordinateur à identifier des associations dans les données. Les cellules fusionnées rendront vos données illisibles pour les logiciels de statistiques. Envisagez de restructurer vos données de manière à ne plus avoir besoin de fusionner des cellules pour les organiser.
Placer des commentaires ou des unités dans des cellules
La plupart des logiciels d’analyse ne peuvent pas lire les commentaires d’Excel ou de LibreOffice, et seraient confus par des commentaires placés dans les cellules de vos données. Comme décrit précédemment pour la mise en forme, créez un autre champ si vous devez ajouter des notes dans les cellules. De même, n’incluez pas d’unités dans les cellules : idéalement, toutes les mesures que vous placez dans une seule colonne doivent être dans la même unité, mais si pour une raison quelconque ce n’est pas le cas, créez un autre champ et précisez l’unité à laquelle appartient la cellule.
Saisir plus d’une information dans une cellule
Exemple : Enregistrer les groupes ABO et Rhesus dans une seule cellule, par exemple A+, B+, A-, …
Solution : Ne regroupez pas plusieurs informations dans une même cellule, car cela limite les possibilités d’analyse de vos données. Si vous avez besoin de ces deux mesures, concevez votre feuille de données pour les enregistrer séparément. Par exemple, prévoyez une colonne pour le groupe ABO et une autre pour le groupe Rhésus.
Utilisation de noms de champs problématiques
Choisissez des noms de champs descriptifs, mais veillez à ne pas inclure d’espaces, de chiffres ou de caractères spéciaux de quelque nature que ce soit. Les espaces peuvent être interprétés à tort par des analyseurs qui utilisent l’espace blanc comme délimiteur, et certains programmes ne supportent pas les noms de champs qui sont des chaînes de texte commençant par des chiffres.
Les tirets bas (_) constituent une bonne alternative aux
espaces. Envisagez d’écrire les noms en camel case (comme ceci :
ExampleFileName) pour améliorer la lisibilité. Gardez à l’esprit que des
abréviations qui ont du sens aujourd’hui ne seront peut-être plus aussi
évidentes dans six mois, mais n’exagérez pas non plus avec des noms
excessivement longs. Inclure les unités dans les noms de champs évite
toute confusion et permet aux autres de les interpréter facilement.
Exemples
| Bon nom | Bonne alternative | Éviter |
|---|---|---|
| Max_temp_C | MaxTemp | Maximum Temp (°C) |
| Precipitation_mm | Precipitation | precmm |
| Mean_year_growth | MeanYearGrowth | Mean growth/year |
| sex | sex | M/F |
| weight | weight | w. |
| cell_type | CellType | Cell Type |
| Observation_01 | first_observation | 1st Obs |
Utilisation de caractères spéciaux dans les données
Exemple : Vous traitez votre logiciel de feuille de calcul comme un traitement de texte lorsque vous rédigez des notes, par exemple en copiant des données directement depuis Word ou d’autres applications.
Solution : Il s’agit d’une stratégie courante. Par exemple, lorsqu’on rédige un texte plus long dans une cellule, on inclut souvent des sauts de ligne, des tirets longs, etc., dans sa feuille de calcul. De même, lors de la copie de données depuis des applications telles que Word, le formatage et des caractères non standard complexes (tels que des guillemets alignés à gauche ou à droite) sont inclus. Lors de l’exportation de ces données vers un environnement de programmation/statistique ou vers une base de données relationnelle, des problèmes dangereux peuvent survenir, comme la coupure de lignes en deux ou l’apparition d’erreurs d’encodage.
La bonne pratique générale consiste à éviter d’ajouter des caractères tels que des sauts de ligne, des tabulations et des tabulations verticales. En d’autres termes, traitez une cellule de texte comme un simple formulaire web ne pouvant contenir que du texte et des espaces.
Inclusion de métadonnées dans la table de données
Exemple : Vous ajoutez une légende en haut ou en bas de votre tableau de données expliquant la signification des colonnes, les unités, les exceptions, etc.
Solution : L’enregistrement des informations relatives à vos données (« métadonnées ») est essentiel. Vous connaissez peut-être par cœur votre jeu de données pendant que vous les collectez et les analysez, mais il est peu probable que vous vous souveniez, après quelques mois, un an ou plus, que la variable « sglmemgp » signifie membre unique d’un groupe, par exemple, ou de l’algorithme exact que vous avez utilisé pour transformer une variable ou en créer une dérivée.
Par ailleurs, il existe de nombreuses raisons pour lesquelles d’autres personnes pourraient souhaiter examiner ou utiliser vos données : comprendre vos résultats, les vérifier, examiner votre publication soumise, reproduire vos résultats, concevoir une étude similaire, ou même archiver vos données pour permettre l’accès et la réutilisation par d’autres. Bien que les données numériques soient par définition lisibles par machine, comprendre leur signification est une tâche réservée aux êtres humains. L’importance de documenter vos données durant la phase de collecte et d’analyse de votre recherche ne peut être surestimée, surtout si votre recherche doit faire partie du registre scientifique.
Toutefois, les métadonnées ne doivent pas figurer dans le fichier de données lui-même. Contrairement à un tableau dans un article ou à un fichier supplémentaire, les métadonnées (sous la forme de légendes) ne doivent pas être incluses dans un fichier de données, car ces informations ne sont pas des données, et leur inclusion peut perturber la manière dont les programmes informatiques interprètent votre fichier de données. Au lieu de cela, les métadonnées doivent être stockées dans un fichier distinct dans le même répertoire que votre fichier de données, idéalement au format texte brut, avec un nom qui l’associe clairement à votre fichier de données. Comme les fichiers de métadonnées sont au format texte libre, ils vous permettent également de coder des commentaires, des unités, des informations sur la manière dont les valeurs nulles sont codées, etc., lesquelles sont importantes à documenter mais peuvent perturber le formatage de votre fichier de données.
De plus, les métadonnées au niveau des fichiers ou de la base de données décrivent les relations entre les fichiers qui composent le jeu de données, leur format et s’ils remplacent d’autres fichiers ou ont eux-mêmes été remplacés. Un fichier readme.txt placé dans le dossier est le moyen habituel de recenser tous les fichiers et dossiers d’un projet.
(Le texte sur les métadonnées est adapté du cours en ligne Research Data MANTRA d’EDINA et de la Data Library de l’Université d’Édimbourg. MANTRA est sous licence Creative Commons Attribution 4.0 International License.)
Exportation de données
Question
- Comment exporter des données à partir de feuilles de calcul de manière à ce qu’elles soient utiles pour des applications ultérieures ?
Objectifs
- Stocker les données de feuilles de calcul dans des formats de fichiers universels.
- Exporter des données depuis une feuille de calcul vers un fichier CSV.
Points clés
Les données stockées dans des formats de feuilles de calcul courants ne seront souvent pas lues correctement par les logiciels d’analyse de données, ce qui introduit des erreurs dans vos données.
L’exportation de données depuis des feuilles de calcul vers des formats tels que le CSV ou le TSV les place dans un format utilisable de manière cohérente par la plupart des programmes.
Stocker les données que vous allez utiliser pour vos analyses dans le
format de fichier par défaut d’Excel (*.xls ou
*.xlsx - selon la version d’Excel) n’est pas une bonne
idée. Pourquoi ?
Parce qu’il s’agit d’un format propriétaire et qu’à l’avenir, la technologie permettant d’ouvrir le fichier pourrait disparaître ou devenir très rare, ce qui rendrait l’ouverture du fichier difficile, voire impossible.
D’autres logiciels de feuilles de calcul pourraient ne pas être capables d’ouvrir des fichiers enregistrés au format propriétaire d’Excel.
Différentes versions d’Excel peuvent traiter les données différemment, ce qui peut entraîner des incohérences. Les dates constituent un exemple bien documenté d’incohérences dans la conservation des données.
Enfin, un nombre croissant de revues et d’organismes de financement exigent que vous déposiez vos données dans un dépôt de données, et la plupart d’entre eux n’acceptent pas le format Excel. Elle doit être dans l’un des formats abordés ci-dessous.
Les points mentionnés ci-dessus s’appliquent également à d’autres formats, tels que les formats de données ouvertes utilisés par LibreOffice / Open Office. Ces formats ne sont pas statiques et ne sont pas analysés de la même manière par différents logiciels.
Le stockage des données dans un format universel, ouvert et statique aidera à remédier à ce problème. Essayez le format tabulé (valeurs séparées par des tabulations ou TSV) ou le format séparé par des virgules (valeurs séparées par des virgules ou CSV). Les fichiers CSV sont des fichiers texte brut où les colonnes sont séparées par des virgules, d’où le nom « valeurs séparées par des virgules » ou CSV. L’avantage d’un fichier CSV par rapport à un fichier Excel/SPSS/etc. est que nous pouvons ouvrir et lire un fichier CSV avec pratiquement n’importe quel logiciel, y compris des éditeurs de texte brut comme TextEdit ou le Bloc-notes. Les données d’un fichier CSV peuvent également être facilement importées dans d’autres formats et environnements, tels que SQLite et R. Nous ne sommes pas liés à une version spécifique d’un programme coûteux lorsque nous travaillons avec des fichiers CSV ; c’est donc un bon format pour garantir une portabilité et une pérennité maximales. La plupart des logiciels de feuilles de calcul peuvent enregistrer facilement dans des formats texte délimités comme le CSV, bien qu’ils puissent vous afficher un avertissement lors de l’exportation du fichier.
Pour enregistrer un fichier ouvert dans Excel au format CSV :
- Dans le menu supérieur, sélectionnez « Fichier » et « Enregistrer sous ».
- Dans le champ « Format », sélectionnez « Valeurs séparées par des
virgules » (
*.csv) dans la liste. - Vérifiez à nouveau le nom du fichier et l’emplacement où vous souhaitez le enregistrer, puis cliquez sur « Enregistrer ».
Une note importante pour la rétrocompatibilité : vous pouvez ouvrir des fichiers CSV dans Excel !

Note sur R et xls : Il existe des
packages R capables de lire les fichiers xls (ainsi que les
feuilles de calcul Google). Il est même possible d’accéder à différentes
feuilles de calcul dans les documents xls.
Mais
- certains d’entre eux ne fonctionnent que sous Windows.
- cela revient à remplacer un export (simple mais manuel) vers
csvpar une complexité/des dépendances supplémentaires dans le code R d’analyse de données. - Les bonnes pratiques de mise en forme des données s’appliquent toujours.
- Y a-t-il vraiment une bonne raison pour laquelle
csv(ou un élément similaire) ne convient pas ?
Précautions concernant les virgules
Dans certains jeux de données, les valeurs elles-mêmes peuvent contenir des virgules (,). Dans ce cas, le logiciel que vous utilisez (y compris Excel) affichera très probablement les données de manière incorrecte dans des colonnes. Cela est dû au fait que les virgules faisant partie des valeurs de données seront interprétées comme des délimiteurs.
Par exemple, nos données pourraient ressembler à ceci :
species_id,genus,species,taxa
AB,Amphispiza,bilineata,Bird
AH,Ammospermophilus,harrisi,Rodent, not censused
AS,Ammodramus,savannarum,Bird
BA,Baiomys,taylori,Rodent
Dans le enregistrement
AH,Ammospermophilus,harrisi,Rodent, not censused, la valeur
de taxa contient une virgule
(Rodent, not censused). Si nous tentons de lire ce qui
précède dans Excel (ou un autre programme de feuille de calcul), nous
obtiendrons quelque chose comme ceci :

La valeur de taxa a été divisée en deux colonnes (au
lieu d’être placée dans une seule colonne D). Cela peut
entraîner un certain nombre d’erreurs supplémentaires. Par exemple, la
colonne supplémentaire sera interprétée comme une colonne contenant de
nombreuses valeurs manquantes (et sans en-tête approprié). De plus, la
valeur de la colonne D pour l’enregistrement de la ligne 3
(c’est-à-dire celui où la valeur de « taxa » contenait la virgule) est
désormais incorrecte.
Si vous souhaitez stocker vos données au format csv et
que vous prévoyez que vos valeurs puissent contenir des virgules, vous
pouvez éviter le problème décrit ci-dessus en entourant les valeurs de
guillemets (““). En appliquant cette règle, nos données pourraient
ressembler à ceci :
species_id,genus,species,taxa
"AB","Amphispiza","bilineata","Bird"
"AH","Ammospermophilus","harrisi","Rodent, not censused"
"AS","Ammodramus","savannarum","Bird"
"BA","Baiomys","taylori","Rodent"
Désormais, l’ouverture de ce fichier en tant que csv
dans Excel ne provoquera pas d’ajout de colonne, car Excel n’utilisera
que les virgules situées en dehors des guillemets comme caractères de
délimitation.
Alternativement, si vous travaillez avec des données contenant des virgules, vous devrez probablement utiliser un autre délimiteur lorsque vous travaillez dans une feuille de calcul1. Dans ce cas, envisagez d’utiliser des tabulations comme délimiteur et de travailler avec des fichiers TSV. Les fichiers TSV peuvent être exportés depuis des logiciels de feuilles de calcul de la même manière que les fichiers CSV.
Si vous travaillez avec un jeu de données existant dans lequel les valeurs ne sont pas entourées de “” mais qui utilisent des virgules à la fois comme séparateurs et comme éléments des valeurs, vous êtes potentiellement confronté à un problème majeur de nettoyage des données. Si le jeu de données que vous manipulez contient des centaines ou des milliers de lignes, les nettoyer manuellement (en supprimant les virgules des valeurs ou en plaçant les valeurs entre guillemets - ““) ne nécessitera pas seulement des heures et des heures, mais pourrait également entraîner l’introduction accidentelle de nombreuses erreurs.
Le nettoyage des jeux de données est l’un des problèmes majeurs dans de nombreuses disciplines scientifiques. L’approche dépend presque toujours du contexte particulier. Toutefois, il est recommandé de nettoyer les données de manière automatisée, par exemple en écrivant et en exécutant un script. Les leçons sur Python et R vous fourniront les bases nécessaires pour développer des compétences en matière de création de scripts adaptés.
Résumé

Un flux de travail typique d’analyse de données est illustré sur la figure ci-dessus, où les données sont à plusieurs reprises transformées, visualisées et modélisées. Cette itération est répétée plusieurs fois jusqu’à ce que les données soient comprises. Dans de nombreux cas concrets, cependant, la majeure partie du temps est consacrée au nettoyage et à la préparation des données, plutôt qu’à leur analyse et à leur compréhension effectives.
Un flux de travail d’analyse de données agile, comprenant plusieurs itérations rapides du cycle transformation/visualisation/modélisation, n’est réalisable que si les données sont formatées de manière prévisible et qu’il est possible de raisonner à partir d’elles sans avoir à les consulter et/ou à les corriger.
- Une bonne organisation des données est le fondement de tout projet de recherche.
Cela est particulièrement pertinent dans les pays européens où la virgule est utilisée comme séparateur décimal. Dans ce cas, le séparateur de valeurs par défaut dans un fichier CSV sera le point-virgule (;), ou les valeurs seront systématiquement mises entre guillemets.↩︎
Content from R et RStudio
Last updated on 2026-11-07 | Edit this page
Estimated time: 30 minutes
Overview
Questions
- Qu’est-ce que R et RStudio ?
Objectives
- Décrivez le rôle des panneaux Script, Console, Environment et Plots de RStudio.
- Organiser les fichiers et les répertoires pour un ensemble d’analyses sous la forme d’un projet R, et comprendre l’utilité du répertoire de travail.
- Utilisez l’interface d’aide intégrée à RStudio pour rechercher plus d’informations sur les fonctions R.
- Démontrer comment fournir suffisamment d’informations pour dépanner auprès de la communauté d’utilisateurs de R.
Cet épisode est basé sur la leçon Data Analysis and Visualisation in R for Ecologists de Data Carpentries.
Qu’est-ce que R ? Qu’est-ce que RStudio ?
Le terme R est utilisé pour désigner le langage de programmation, l’environnement de calcul statistique et le logiciel qui interprète les scripts écrits avec celui-ci.
RStudio est actuellement un moyen très populaire non seulement d’écrire vos scripts R, mais aussi d’interagir avec le logiciel R1. Pour fonctionner correctement, RStudio nécessite R et, par conséquent, les deux doivent être installés sur votre ordinateur.
La fiche pratique de l’IDE RStudio fournit bien plus d’informations que celles qui seront abordées ici, mais peut s’avérer utile pour apprendre les raccourcis clavier et découvrir de nouvelles fonctionnalités.
Pourquoi apprendre R ?
R ne nécessite pas beaucoup de clics, et c’est une bonne chose.
La courbe d’apprentissage peut être plus abrupte qu’avec d’autres logiciels, mais avec R, les résultats de votre analyse ne dépendent pas du fait de mémoriser une succession de clics, mais plutôt d’une série de commandes écrites, et c’est une bonne chose ! Ainsi, si vous souhaitez refaire votre analyse parce que vous avez collecté davantage de données, vous n’avez pas à vous rappeler quel bouton vous avez cliqué et dans quel ordre pour obtenir vos résultats ; il vous suffit de relancer votre script.
Le travail avec des scripts rend les étapes utilisées dans votre analyse claires, et le code que vous écrivez peut être examiné par une autre personne capable de vous fournir des retours et de repérer des erreurs.
Le travail avec des scripts vous oblige à avoir une compréhension plus approfondie de ce que vous faites, et facilite votre apprentissage et votre compréhension des méthodes que vous utilisez.
Le code R est idéal pour la reproductibilité
La reproductibilité signifie qu’une autre personne (y compris votre futur soi) peut obtenir les mêmes résultats à partir du même jeu de données en utilisant le même code d’analyse.
R s’intègre à d’autres outils pour générer des manuscrits ou des rapports à partir de votre code. Si vous collectez davantage de données ou corrigez une erreur dans votre jeu de données, les figures et les tests statistiques de votre manuscrit ou de votre rapport sont mis à jour automatiquement.
Un nombre croissant de revues et d’organismes de financement exigent que les analyses soient reproductibles ; maîtriser R vous donnera donc un avantage face à ces exigences.
R est interdisciplinaire et extensible
Avec plus de 10 000 packages2 pouvant être installés pour en étendre les capacités, R offre un cadre qui vous permet de combiner des approches statistiques issues de nombreuses disciplines scientifiques afin d’adapter au mieux le cadre analytique nécessaire à l’analyse de vos données. Par exemple, R dispose de packages pour l’analyse d’images, la SIG, les séries temporelles, la génétique des populations, et bien plus encore.

R fonctionne avec des données de toutes formes et de toutes tailles
Les compétences que vous acquérez avec R s’adaptent facilement à la taille de votre jeu de données. Que votre jeu de données compte des centaines ou des millions de lignes, cela ne fera pas grande différence pour vous.
R est conçu pour l’analyse de données. Il dispose de structures de données et de types de données spéciaux qui facilitent la manipulation des données manquantes et des facteurs statistiques.
R peut se connecter à des feuilles de calcul, à des bases de données et à de nombreux autres formats de données, sur votre ordinateur ou sur le Web.
R produit des graphiques de haute qualité
Les fonctionnalités de tracé de R sont vastes et vous permettent d’ajuster tout aspect de votre graphique afin de transmettre le message de vos données de la manière la plus efficace possible.
R dispose d’une communauté vaste et accueillante
Des milliers de personnes utilisent R quotidiennement. Beaucoup d’entre elles sont prêtes à vous aider via des listes de diffusion et des sites web tels que Stack Overflow, ou sur la communauté RStudio. Ces vastes communautés d’utilisateurs s’étendent à des domaines spécialisés tels que la bioinformatique. L’un de ces sous-ensembles de la communauté R est Bioconductor, un projet scientifique d’analyse et de compréhension « des données issues d’essais biologiques actuels et émergents ». Cet atelier a été développé par des membres de la communauté Bioconductor ; pour plus d’informations sur Bioconductor, veuillez consulter l’atelier complémentaire “The Bioconductor Project”.
R est non seulement gratuit, mais il est également open source et multiplateforme.
Tout le monde peut examiner le code source pour voir comment R fonctionne. Grâce à cette transparence, les risques d’erreurs sont réduits et, si vous (ou quelqu’un d’autre) en trouvez, il est possible de signaler et de corriger des bugs.
Se familiariser avec RStudio
Commençons par découvrir RStudio, un environnement de développement intégré (IDE) pour travailler avec R.
Le produit open source RStudio IDE est gratuit sous la Licence publique générale Affero (AGPL) v3. RStudio IDE est également disponible avec une licence commerciale et un support par e-mail prioritaire de la part de Posit, Inc.
Nous utiliserons l’IDE RStudio pour écrire du code, naviguer dans les fichiers de notre ordinateur, examiner les variables que nous allons créer et visualiser les graphiques que nous générerons. RStudio peut également être utilisé pour d’autres tâches (par exemple, la gestion des versions, le développement de packages, la création d’applications Shiny) que nous ne traiterons pas durant l’atelier.

La fenêtre de RStudio est divisée en quatre « panneaux » :
- la Source pour vos scripts et documents (en haut à gauche, dans la disposition par défaut)
- votre panneau Environment/History (environnement/historique, en haut à droite),
- votre panneau Files/Plots/Packages/Help/Viewer (fichiers/graphiques/paquets/aide/visualiseur, en bas à droite), et
- la Console de R (en bas à gauche).
L’emplacement de ces panneaux et leur contenu peuvent être
personnalisés (voir le menu
Tools -> Global Options -> Pane Layout).
L’un des avantages de RStudio est que toutes les informations nécessaires pour écrire du code sont disponibles dans une seule fenêtre. De plus, grâce à de nombreux raccourcis, à l’autocomplétion et à la coloration syntaxique des principaux types de fichiers utilisés lors du développement en R, RStudio facilite la saisie et réduit les risques d’erreur.
Configuration
Il est recommandé de regrouper un ensemble de données, d’analyses et de textes connexes au sein d’un seul dossier, appelé répertoire de travail. Tous les scripts contenus dans ce dossier peuvent alors utiliser des chemins relatifs vers les fichiers, indiquant l’emplacement d’un fichier au sein du projet (contrairement aux chemins absolus, qui indiquent l’emplacement d’un fichier sur un ordinateur spécifique). Travailler ainsi permet de déplacer beaucoup plus facilement son projet sur son ordinateur et de le partager avec d’autres sans se soucier de savoir si les scripts sous-jacents fonctionneront toujours.
RStudio propose un ensemble d’outils utiles pour ce faire via son interface « Projets », qui non seulement crée un répertoire de travail pour vous, mais mémorise également son emplacement (vous permettant de vous y rendre rapidement) et, optionnellement, conserve les paramètres personnalisés et les fichiers ouverts pour faciliter la reprise du travail après une pause. Suivez ci-dessous les étapes pour créer un « Projet R » pour ce tutoriel.
- Lancez RStudio.
- Dans le menu
File, cliquez surNew project. ChoisissezNew directory, puisNew project. - Saisissez un nom pour ce nouveau dossier (ou « répertoire ») et
choisissez un emplacement pratique. Ce sera votre répertoire de
travail pour cette session (ou pour l’ensemble du cours) (par
ex.,
bioc-intro). - Cliquez sur
Create project. - (Facultatif) Configurez RStudio pour ne jamais enregistrer l’espace de travail en choisissant l’option « Never » dans les préférences.
Les préférences par défaut de RStudio fonctionnent généralement bien, mais enregistrer l’espace de travail dans un fichier .RData peut s’avérer contraignant, surtout avec des jeux de données volumineux. Pour désactiver cette fonctionnalité, ouvrez Tools –> « Global Options », puis choisissez « Never » pour l’option « Save workspace to .RData on exit ».

Afin d’éviter les problèmes de codage de caractères entre Windows et les autres systèmes d’exploitation, nous allons définir UTF-8 par défaut :

Organisation de votre répertoire de travail
L’utilisation d’une structure de dossiers cohérente à travers vos projets vous aidera à rester organisé et vous permettra également de retrouver et de classer vos éléments plus facilement à l’avenir. Cela peut s’avérer particulièrement utile lorsque vous avez plusieurs projets. En général, vous pouvez créer des répertoires (dossiers) pour les scripts, les données et les documents.
-
data/Utilisez ce dossier pour stocker vos données brutes et les jeux de données intermédiaires que vous pourriez créer pour un analyse particulière. Par souci de transparence et de provenance, vous devriez toujours garder une copie de vos données brutes accessible et effectuer autant que possible le nettoyage et le prétraitement de vos données de manière programmatique (c’est-à-dire via des scripts, plutôt que manuellement). Séparer les données brutes des données traitées est également une bonne idée. Par exemple, vous pourriez conserver les fichiersdata/raw/tree_survey.plot1.txtet...plot2.txtséparément d’un fichierdata/processed/tree.survey.csvgénéré par le scriptscripts/01.preprocess.tree_survey.R. -
documents/Ce serait un endroit pour conserver des plans, des brouillons et d’autres textes. -
scripts/(ousrc) Ce serait l’emplacement où vous conserveriez vos scripts R pour différentes analyses ou des tracés, et éventuellement un dossier distinct pour vos fonctions (on y reviendra plus tard).
Vous pourriez avoir besoin de répertoires ou de sous-répertoires supplémentaires selon les besoins de votre projet, mais ceux-ci doivent constituer l’ossature de votre répertoire de travail.

Pour ce cours, nous aurons besoin d’un dossier data/
pour stocker nos données brutes, et nous utiliserons
data_output/ lorsque nous apprendrons à exporter des
données sous forme de fichiers CSV, ainsi que le dossier
fig_output/ pour les figures que nous enregistrerons.
Défi : créez la structure de votre répertoire de projet
Sous l’onglet Files à droite de l’écran, cliquez sur
New Folder et créez un dossier nommé data au
sein de votre répertoire de travail nouvellement créé (par ex.,
~/bioc-intro/data). (Alternativement, saisissez
dir.create("data") dans votre console R.) Répétez ces
opérations pour créer des dossiers data_output/ et
fig_output.
Nous allons conserver le script à la racine de notre répertoire de travail car nous n’utiliserons qu’un seul fichier, ce qui facilitera les choses.
Votre répertoire de travail devrait désormais ressembler à ceci :

La gestion de projet s’applique également aux projets de bioinformatique, bien entendu3. William Noble ( Noble (2009) ) propose la structure de répertoires suivante :
Les noms de répertoires sont dans une police de caractères grande, et les noms de fichiers dans une police plus petite. Seul un sous-ensemble des fichiers est présenté ici. Notez que les dates sont formatées
<year>-<month>-<day>afin qu’elles puissent être triées par ordre chronologique. Le code sourcesrc/ms-analysis.cest compilé pour créerbin/ms-analysiset est documenté dansdoc/ms-analysis.html. Les fichiersREADMEdans les répertoires de données précisent qui a téléchargé les fichiers de données depuis quelle URL et à quelle date. Le script piloteresults/2009-01-15/runallgénère automatiquement les trois sous-répertoires split1, split2 et split3, correspondant à trois partitions de validation croisée. Le scriptbin/parse-sqt.pyest appelé par les deux scripts pilotesrunall.

L’aspect le plus important d’un répertoire de projet bien défini et bien documenté est de permettre à quelqu’un qui ne connaît pas le projet4 de
comprendre de quoi traite le projet, quelles données sont disponibles, quelles analyses ont été réalisées et quels résultats ont été produits et, surtout, de
répéter l’analyse — avec de nouvelles données, ou en modifiant certains paramètres d’analyse.
Le répertoire de travail
Le répertoire de travail est un concept important à comprendre. C’est l’endroit d’où R recherchera et enregistrera les fichiers. Lorsque vous écrivez du code pour votre projet, celui-ci doit faire référence aux fichiers par rapport à la racine de votre répertoire de travail et ne doit référencer que des fichiers situés au sein de cette structure.
L’utilisation de projets RStudio facilite cette tâche et garantit que
votre répertoire de travail est correctement configuré. Si vous devez le
vérifier, vous pouvez utiliser getwd(). Si, pour une raison
quelconque, votre répertoire de travail ne correspond pas à celui
attendu, vous pouvez le modifier dans l’interface de RStudio en vous
rendant dans le navigateur de fichiers où se trouve votre répertoire de
travail, en cliquant sur l’icône d’engrenage bleue More,
puis en sélectionnant Set As Working Directory.
Alternativement, vous pouvez utiliser
setwd("/path/to/working/directory") pour réinitialiser
votre répertoire de travail. Toutefois, vos scripts ne doivent pas
contenir cette ligne, car elle échouera sur l’ordinateur de quelqu’un
d’autre.
Exemple
Le schéma ci-dessous représente le répertoire de travail
bioc-intro avec les sous-répertoires data et
fig_output, ainsi que 2 fichiers dans ce dernier :
bioc-intro/data/
/fig_output/fig1.pdf
/fig_output/fig2.png
Si nous étions dans le répertoire de travail, nous pourrions
référencer le fichier fig1.pdf à l’aide du chemin relatif
bioc-intro/fig_output/fig1.pdf ou du chemin absolu
/home/user/bioc-intro/fig_output/fig1.pdf.
Si nous étions dans le répertoire data, nous
utiliserions le chemin relatif ../fig_output/fig1.pdf ou le
même chemin absolu
/home/user/bioc-intro/fig_output/fig1.pdf.
Interagir avec R
Le principe de la programmation consiste à rédiger des instructions que l’ordinateur doit suivre, puis à lui demander de les exécuter. Nous rédigeons, ou codons, des instructions en R, car c’est un langage commun que l’ordinateur et nous pouvons comprendre. Nous appelons ces instructions des commandes et nous demandons à l’ordinateur de les suivre en les exécutant (ou en les lançant).
Il existe deux principales façons d’interagir avec R : en utilisant
la console ou en utilisant des scripts
(fichiers texte bruts contenant votre code). La fenêtre de la console
(dans RStudio, le panneau inférieur à gauche) est l’endroit où l’on peut
saisir des commandes écrites dans le langage R et où l’ordinateur les
exécute immédiatement. C’est également là que les résultats des
commandes exécutées s’affichent. Vous pouvez saisir des commandes
directement dans la console et appuyer sur Enter pour les
exécuter, mais elles seront effacées lorsque vous fermerez la
session.
Comme nous voulons que notre code et notre flux de travail soient reproductibles, il est préférable de saisir les commandes souhaitées dans l’éditeur de scripts et de sauvegarder le script. De cette façon, un registre complet de nos actions subsiste, et n’importe qui (y compris nous-mêmes à l’avenir !) peut facilement reproduire les résultats sur son propre ordinateur. Notez toutefois que le simple fait de saisir les commandes dans le script ne les lance pas automatiquement : elles doivent tout de même être envoyées à la console pour être exécutées.
RStudio vous permet d’exécuter des commandes directement depuis
l’éditeur de scripts en utilisant le raccourci Ctrl +
Enter (sur Mac, Cmd + Return
fonctionne également). La commande de la ligne actuelle du script
(indiquée par le curseur) ou l’ensemble des commandes du texte
actuellement sélectionné sera envoyé à la console et exécuté lorsque
vous appuyerez sur Ctrl + Enter. Vous
trouverez d’autres raccourcis clavier dans ce cheatsheet
RStudio concernant l’IDE RStudio.
À un moment donné de votre analyse, vous souhaiterez peut-être
vérifier le contenu d’une variable ou la structure d’un objet, sans
nécessairement en garder trace dans votre script. Vous pouvez saisir ces
commandes et les exécuter directement dans la console. RStudio propose
les raccourcis Ctrl + 1 et Ctrl +
2 qui vous permettent de basculer entre les fenêtres du
script et de la console.
Lorsque R est prêt à accepter des commandes, la console affiche une
invite >. Lorsqu’il reçoit une commande, saisie
directement, copiée-collée ou envoyée depuis l’éditeur de scripts avec
Ctrl + Enter, R tente de l’exécuter. Une fois
l’exécution terminée, il affiche les résultats, puis une nouvelle invite
> pour attendre de nouvelles commandes.
Si R attend encore une saisie parce que la commande est incomplète,
la console affiche une invite +. Cela signifie que vous
n’avez pas fini de saisir une commande complète. Vous n’avez pas fermé
une parenthèse ou des guillemets : le nombre de parenthèses ouvrantes et
fermantes, ou de guillemets ouvrants et fermants, ne correspond pas. Si
cela se produit alors que vous pensiez avoir terminé votre commande,
cliquez dans la console et appuyez sur Esc ; cela annulera
la commande incomplète et vous ramènera à l’invite
>.
Comment en apprendre davantage pendant et après le cours ?
Le contenu abordé durant ce cours vous donnera un premier aperçu de la manière dont vous pouvez utiliser R pour analyser des données dans le cadre de vos propres recherches. Toutefois, vous devrez en apprendre davantage pour effectuer des opérations avancées, telles que le nettoyage de votre jeu de données, l’utilisation de méthodes statistiques ou la création de graphiques esthétiques5. Le meilleur moyen de devenir maître et efficace avec R, comme pour tout autre outil, est de l’utiliser pour répondre à vos questions de recherche réelles. En tant que débutant, l’idée de devoir écrire un script de zéro peut sembler intimidante et, étant donné que de nombreuses personnes mettent leur code à disposition en ligne, la modification de code existant pour l’adapter à vos besoins pourrait vous faciliter les débuts.

Chercher de l’aide
Utilisez l’interface d’aide intégrée à RStudio pour rechercher plus d’informations sur les fonctions R

L’un des moyens les plus rapides d’obtenir de l’aide consiste à utiliser l’interface d’aide de RStudio. Ce panneau se trouve par défaut dans le panneau inférieur droit de RStudio. Comme on peut le voir sur la capture d’écran, en saisissant le mot « Mean », RStudio tente également de proposer un certain nombre de suggestions qui pourraient vous intéresser. La description s’affiche ensuite dans la fenêtre d’affichage.
Je connais le nom de la fonction que je souhaite utiliser, mais je ne sais pas comment l’utiliser
Si vous avez besoin d’aide pour une fonction spécifique, disons
barplot(), vous pouvez saisir :
R
?barplot
Si vous avez simplement besoin de vous rappeler le nom des arguments, vous pouvez utiliser :
R
args(lm)
Je veux utiliser une fonction qui fait X, il doit y avoir une fonction pour ça, mais je ne sais pas laquelle…
Si vous recherchez une fonction pour effectuer une tâche
particulière, vous pouvez utiliser la fonction
help.search(), qui s’appelle via le double point
d’interrogation ??. Toutefois, celle-ci ne recherche dans
les packages installés que des pages d’aide correspondant à votre
requête de recherche.
R
??kruskal
Si vous ne trouvez pas ce que vous cherchez, vous pouvez utiliser le site rdocumentation.org qui recherche dans les fichiers d’aide de tous les packages disponibles.
Enfin, une recherche Google ou sur Internet générique « R <task> » vous dirigera souvent soit vers la documentation du package approprié, soit vers un forum utile où quelqu’un d’autre a déjà posé votre question.
Je bloque… Je reçois un message d’erreur que je ne comprends pas
Commencez par rechercher le message d’erreur sur Google. Cependant, cela ne fonctionne pas toujours très bien car les développeurs de packages s’appuient souvent sur la gestion des erreurs fournie par R. Vous vous retrouvez avec des messages d’erreur génériques qui pourraient ne pas être très utiles pour diagnostiquer un problème (par exemple : « subscript out of bounds »). Si le message est très générique, vous pouvez également inclure le nom de la fonction ou du package que vous utilisez dans votre requête.
Toutefois, vous devriez consulter Stack Overflow. Effectuez une
recherche en utilisant la balise [r]. La plupart des
questions ont déjà reçu une réponse, mais le défi consiste à utiliser
les bons mots dans votre recherche pour trouver les réponses :
https://stackoverflow.com/questions/tagged/r
L’Introduction à R peut également s’avérer dense pour les personnes ayant peu d’expérience en programmation, mais c’est un bon endroit pour comprendre les fondements du langage R.
La FAQ de R est dense et technique, mais elle regorge d’informations utiles.
Demander de l’aide
La clé pour obtenir de l’aide est que l’interlocuteur saisisse rapidement votre problème. Vous devez faciliter au maximum la localisation du défaut.
Essayez d’utiliser les mots appropriés pour décrire votre problème. Par exemple, un package n’est pas la même chose qu’une bibliothèque. La plupart des gens comprendront ce que vous vouliez dire, mais d’autres ont des opinions très tranchées sur la différence de sens. Le point essentiel est que cela peut prêter à confusion pour les personnes qui tentent de vous aider. Soyez aussi précis que possible lorsque vous décrivez votre problème.
Si possible, essayez de réduire ce qui ne fonctionne pas à un exemple reproductible simple. Si vous pouvez reproduire le problème à l’aide d’un tableau de données très petit au lieu de celui de 50 000 lignes et 10 000 colonnes, fournissez ce petit tableau accompagné de la description de votre problème. Lorsque cela est approprié, essayez de généraliser votre démarche afin que même des personnes n’appartenant pas à votre domaine puissent comprendre la question. Par exemple, au lieu d’utiliser un sous-ensemble de votre jeu de données réel, créez un exemple générique petit (3 colonnes, 5 lignes). Pour plus d’informations sur la manière d’écrire un exemple reproductible, consultez cet article de Hadley Wickham.
Pour partager un objet avec quelqu’un d’autre, s’il est relativement
petit, vous pouvez utiliser la fonction dput(). Elle
générera du code R permettant de recréer exactement le même objet que
celui en mémoire :
R
## iris is an example data frame that comes with R and head() is a
## function that returns the first part of the data frame
dput(head(iris))
OUTPUT
structure(list(Sepal.Length = c(5.1, 4.9, 4.7, 4.6, 5, 5.4),
Sepal.Width = c(3.5, 3, 3.2, 3.1, 3.6, 3.9), Petal.Length = c(1.4,
1.4, 1.3, 1.5, 1.4, 1.7), Petal.Width = c(0.2, 0.2, 0.2,
0.2, 0.2, 0.4), Species = structure(c(1L, 1L, 1L, 1L, 1L,
1L), levels = c("setosa", "versicolor", "virginica"), class = "factor")), row.names = c(NA,
6L), class = "data.frame")
Si l’objet est plus volumineux, fournissez soit le fichier brut (c’est-à-dire votre fichier CSV) avec votre script jusqu’au point où survient l’erreur (et après avoir supprimé tout ce qui n’est pas pertinent pour votre problème). Alternativement, notamment si votre question n’est pas liée à un tableau de données, vous pouvez enregistrer n’importe quel objet R dans un fichier[^export] :
R
saveRDS(iris, file="/tmp/iris.rds")
Le contenu de ce fichier n’est toutefois pas lisible par l’humain et
ne peut pas être publié directement sur Stack Overflow. On peut plutôt
l’envoyer par e-mail à quelqu’un qui pourra le lire à l’aide de la
commande readRDS() (on suppose ici que le fichier
téléchargé se trouve dans un dossier Downloads dans le
répertoire personnel de l’utilisateur) :
R
some_data <- readRDS(file="~/Downloads/iris.rds")
Enfin, mais certainement pas des moindres, incluez toujours
la sortie de sessionInfo(), car elle fournit des
informations cruciales sur votre plateforme, les versions de R et des
packages que vous utilisez, ainsi que d’autres informations qui peuvent
s’avérer très utiles pour comprendre votre problème.
R
sessionInfo()
OUTPUT
R version 4.6.1 (2026-06-24)
Platform: x86_64-pc-linux-gnu
Running under: Ubuntu 24.04.5 LTS
Matrix products: default
BLAS: /usr/lib/x86_64-linux-gnu/openblas-pthread/libblas.so.3
LAPACK: /usr/lib/x86_64-linux-gnu/openblas-pthread/libopenblasp-r0.3.26.so; LAPACK version 3.12.0
locale:
[1] LC_CTYPE=C.UTF-8 LC_NUMERIC=C LC_TIME=C.UTF-8
[4] LC_COLLATE=C.UTF-8 LC_MONETARY=C.UTF-8 LC_MESSAGES=C.UTF-8
[7] LC_PAPER=C.UTF-8 LC_NAME=C LC_ADDRESS=C
[10] LC_TELEPHONE=C LC_MEASUREMENT=C.UTF-8 LC_IDENTIFICATION=C
time zone: UTC
tzcode source: system (glibc)
attached base packages:
[1] stats graphics grDevices utils datasets methods base
loaded via a namespace (and not attached):
[1] compiler_4.6.1 cli_3.6.6 tools_4.6.1 otel_0.2.0 knitr_1.52
[6] xfun_0.62 rlang_1.3.0 evaluate_1.0.5
Où demander de l’aide ?
- La personne assise à vos côtés pendant le cours. N’hésitez pas à discuter avec votre voisin pendant l’atelier, à comparer vos réponses et à demander de l’aide.
- Vos collègues sympathiques : si vous connaissez quelqu’un ayant plus d’expérience que vous, il pourrait être en mesure et disposé à vous aider.
- Stack Overflow : si votre question n’a jamais été traitée auparavant et qu’elle est bien formulée, vous avez de bonnes chances d’obtenir une réponse en moins de 5 min. N’oubliez pas de suivre leurs recommandations sur la manière de poser une bonne question.
- La liste de diffusion R-help : elle est consultée par de nombreuses personnes (dont la plupart de l’équipe principale de R), et beaucoup y publient, mais le ton peut être assez sec et elle n’est pas toujours très accueillante pour les nouveaux utilisateurs. Si votre question est pertinente, vous obtiendrez probablement une réponse très rapidement, mais ne vous attendez pas à ce qu’elle soit accompagnée d’émoticônes. De plus, ici plus qu’ailleurs, veillez à utiliser un vocabulaire correct (sinon, vous pourriez recevoir une réponse soulignant l’usage incorrect de vos mots plutôt que de répondre à votre question). Vous aurez également plus de succès si votre question porte sur une fonction de base plutôt que sur un package spécifique.
- Si votre question concerne un package spécifique, vérifiez s’il
existe une liste de diffusion à son sujet. Généralement, elle figure
dans le fichier DESCRIPTION du package, accessible via
packageDescription("name-of-package"). Vous pouvez également essayer d’envoyer un e-mail directement à l’auteur du package ou d’ouvrir un ticket dans le dépôt de code (par exemple, sur GitHub). - Il existe également des listes de diffusion spécialisées par thème (SIG, phylogénétique, etc…), la liste complète est disponible sur la page des listes de diffusion de R-project.
Plus de ressources
Le Guide de publication pour les listes de diffusion R.
Comment demander de l’aide pour R : des directives utiles.
Cet article de blog de Jon Skeet propose des conseils assez complets sur la manière de poser des questions de programmation.
Le package reprex est très utile pour créer des exemples reproductibles lorsque l’on demande de l’aide. La réunion en ligne de la communauté rOpenSci intitulée « How to ask questions so they get answered » (lien GitHub et enregistrement vidéo) comprend une présentation du package reprex et de sa philosophie.
Paquets R
Chargement de packages
Comme nous l’avons vu plus haut, les packages R jouent un rôle
fondamental dans R. Pour utiliser les fonctionnalités d’un package, à
condition qu’il soit installé, nous devons d’abord le charger afin de
pouvoir l’utiliser. Cela se fait avec la fonction
library(). Ci-dessous, nous chargeons
ggplot2.
R
library("ggplot2")
Installation de packages
Le dépôt de packages par défaut est le Comprehensive R Archive
Network (CRAN), et tout package disponible sur CRAN peut être
installé avec la fonction install.packages(). Ci-dessous,
par exemple, nous installons le package dplyr que nous
découvrirons plus tard.
R
install.packages("dplyr")
Cette commande installera le package dplyr ainsi que
toutes ses dépendances, c’est-à-dire tous les packages dont il a besoin
pour fonctionner.
Un autre dépôt majeur de packages R est géré par Bioconductor. Les packages
Bioconductor sont gérés et installés à l’aide d’un package dédié, à
savoir BiocManager, qui peut être installé depuis CRAN
avec
R
install.packages("BiocManager")
Des packages individuels tels que SummarizedExperiment
(nous l’utiliserons plus tard), DESeq2 (pour l’analyse
RNA-Seq) et tout autre provenant de Bioconductor ou de CRAN peuvent
ensuite être installés avec BiocManager::install.
R
BiocManager::install("SummarizedExperiment")
BiocManager::install("DESeq2")
Par défaut, BiocManager::install() vérifiera également
tous vos packages installés pour voir s’il existe des versions plus
récentes. Si c’est le cas, il vous les présentera et vous demandera si
vous souhaitez Update all/some/none? [a/s/n]:, puis
attendra votre réponse. Bien que vous devriez vous efforcer d’avoir les
versions de packages les plus récentes, nous recommandons en pratique de
ne mettre à jour les packages que lors d’une session R neuve, avant
qu’aucun package ne soit chargé.
- Commencer à utiliser R et RStudio
Contrairement à l’utilisation de R directement depuis la console de ligne de commande. Il existe d’autres logiciels qui s’interfacent et s’intègrent à R, mais RStudio est particulièrement adapté aux débutants tout en offrant de nombreuses fonctionnalités très avancées.↩︎
c’est-à-dire des extensions qui confèrent à R de nouvelles fonctionnalités, telles que l’analyse de données en bioinformatique.↩︎
Dans ce cours, nous considérons la bioinformatique comme une science des données appliquée aux données biologiques ou biomédicales.↩︎
Cette personne pourrait être, et sera très probablement, vous-même dans quelques mois ou quelques années après la réalisation des analyses.↩︎
Nous présenterons la plupart d’entre eux ici (à l’exception des statistiques), mais nous ne parviendrons qu’à effleurer la surface de la richesse des possibilités offertes par R.↩︎
Content from Introduction à R
Last updated on 2026-11-07 | Edit this page
Estimated time: 120 minutes
Overview
Questions
- Premières commandes en R
Objectives
- Définissez les termes suivants en lien avec R : objet, affecter, appeler, fonction, arguments, options.
- Attribuer des valeurs à des objets dans R.
- Apprendre à nommer des objets
- Utiliser des commentaires pour éclairer le script.
- Résoudre des opérations arithmétiques simples dans R.
- Appeler des fonctions et utiliser des arguments pour modifier leurs options par défaut.
- Examiner le contenu des vecteurs et en manipuler le contenu.
- Sélectionner des sous-ensembles de vecteurs et en extraire des valeurs.
- Analyser des vecteurs contenant des données manquantes.
Cet épisode est basé sur la leçon Data Analysis and Visualisation in R for Ecologists de Data Carpentries.
Création d’objets dans R
Vous pouvez obtenir des résultats depuis R en saisissant simplement des expressions mathématiques dans la console :
R
3 + 5
OUTPUT
[1] 8
R
12 / 7
OUTPUT
[1] 1.714286
Cependant, pour faire des choses utiles et intéressantes, nous devons
affecter des valeurs à des objets. Pour créer un
objet, nous devons lui donner un nom suivi de l’opérateur d’affectation
<-, puis de la valeur que nous souhaitons lui affecter
:
R
weight_kg <- 55
<- est l’opérateur d’affectation. Il attribue des
valeurs à droite à des objets à gauche. Ainsi, après avoir exécuté
x <- 3, la valeur de x est 3.
La flèche peut être lue comme 3 va dans x.
Pour des raisons historiques, vous pouvez également utiliser
= pour les affectations, mais pas dans tous les contextes.
En raison des légères
différences de syntaxe, il est recommandé d’utiliser toujours
<- pour les affectations.
Dans RStudio, saisir Alt + - (appuyer sur
Alt en même temps que la touche -) permet d’écrire
<- en un seul coup de touche sur un PC, tandis que
saisir Option + - (appuyer sur Option
en même temps que la touche -) fait de même sur un Mac.
Nommer les variables
Les objets peuvent porter n’importe quel nom, tel que x,
current_temperature ou subject_id. Il convient
que les noms de vos objets soient explicites et pas trop longs. Ils ne
peuvent pas commencer par un chiffre (2x n’est pas valide,
mais x2 l’est). R est sensible à la casse (par exemple,
weight_kg est différent de Weight_kg).
Certains noms ne peuvent pas être utilisés car ils correspondent aux
noms de fonctions fondamentales de R (par exemple, if,
else, for ; voir la page du manuel Reserved
Words in R pour une liste complète). En général, même si c’est
autorisé, il est préférable de ne pas utiliser les noms d’autres
fonctions (par exemple, c, T,
mean, data, df,
weights). En cas de doute, consultez l’aide pour voir si le
nom est déjà utilisé. Il est également préférable d’éviter les points
(.) au sein du nom d’un objet, comme dans
my.dataset. De nombreuses fonctions en R contiennent des
points dans leur nom pour des raisons historiques, mais comme les points
ont une signification spéciale en R (pour les méthodes) et dans d’autres
langages de programmation, il est préférable de les éviter. Il est
également recommandé d’utiliser des noms communs pour les objets et des
verbes pour les fonctions. Il est important d’être cohérent dans la mise
en forme de votre code (l’endroit où vous placez les espaces, la manière
dont vous nommez les objets, etc.). L’utilisation d’un style de codage
cohérent rend votre code plus lisible pour vous-même à l’avenir et pour
vos collaborateurs. En R, certains guides de style populaires sont celui
de Google,
le style de tidyverse et le
guide
de style de Bioconductor. Celui de tidyverse est très complet et
peut sembler accablant au début. Vous pouvez installer le package lintr
pour vérifier automatiquement les problèmes de mise en forme de votre
code.
Objets vs. variables : Ce que l’on appelle
objectsdansRest appelévariablesdans de nombreux autres langages de programmation. Selon le contexte,objectetvariablepeuvent avoir des significations radicalement différentes. Cependant, dans cette leçon, les deux termes sont utilisés comme des synonymes. Pour plus d’informations, voir ici.
Lorsqu’on attribue une valeur à un objet, R n’affiche rien. Vous pouvez forcer R à afficher la valeur en utilisant des parenthèses ou en saisissant le nom de l’objet :
R
weight_kg <- 55 # doesn't print anything
(weight_kg <- 55) # but putting parenthesis around the call prints the value of `weight_kg`
OUTPUT
[1] 55
R
weight_kg # and so does typing the name of the object
OUTPUT
[1] 55
Maintenant que R a weight_kg en mémoire, nous pouvons
effectuer des opérations arithmétiques avec celui-ci. Par exemple, nous
souhaiterions peut-être convertir ce poids en livres (le poids en livres
est 2,2 fois le poids en kg) :
R
2.2 * weight_kg
OUTPUT
[1] 121
Nous pouvons également modifier la valeur d’un objet en lui attribuant une nouvelle valeur :
R
weight_kg <- 57.5
2.2 * weight_kg
OUTPUT
[1] 126.5
Cela signifie que l’attribution d’une valeur à un objet ne modifie
pas les valeurs des autres objets. Par exemple, stockons le poids de
l’animal en livres dans un nouvel objet, weight_lb :
R
weight_lb <- 2.2 * weight_kg
puis modifier weight_kg en 100.
R
weight_kg <- 100
Défi :
Selon vous, quel est le contenu actuel de l’objet
weight_lb ? 126.5 ou 220 ?
Commentaires
Le caractère de commentaire dans R est # ; tout ce qui
se trouve à droite d’un # dans un script sera ignoré par R.
Il est utile de laisser des notes et des explications dans vos
scripts.
RStudio permet de commenter ou de décommenter facilement un paragraphe : après avoir sélectionné les lignes que vous souhaitez commenter, appuyez simultanément sur Ctrl + Shift + C sur votre clavier. Si vous ne souhaitez commenter qu’une seule ligne, vous pouvez placer le curseur n’importe où sur cette ligne (c’est-à-dire qu’il n’est pas nécessaire de sélectionner l’intégralité de la ligne), puis appuyer sur Ctrl + Shift + C.
Défi
Quelles sont les valeurs après chaque instruction dans ce qui suit ?
R
mass <- 47.5 # mass?
age <- 122 # age?
mass <- mass * 2.0 # mass?
age <- age - 20 # age?
mass_index <- mass/age # mass_index?
Fonctions et leurs arguments
Les fonctions sont des « scripts préparés » qui automatisent des
ensembles de commandes plus complexes, notamment des opérations
d’affectation, etc. De nombreuses fonctions sont prédéfinies, ou peuvent
être rendues disponibles en important des packages R (on en
reparlera plus tard). Une fonction reçoit généralement un ou plusieurs
paramètres appelés arguments. Les fonctions renvoient souvent
(mais pas toujours) une valeur. Un exemple type serait la
fonction sqrt(). L’entrée (l’argument) doit être un nombre,
et la valeur de retour (en fait, la sortie) est la racine carrée de ce
nombre. L’exécution d’une fonction (« son lancement ») est appelée
appel de la fonction. Un exemple d’appel de fonction est :
R
b <- sqrt(a)
Ici, la valeur de a est transmise à la fonction
sqrt(), la fonction sqrt() calcule la racine
carrée et renvoie la valeur qui est ensuite affectée à l’objet
b. Cette fonction est très simple, car elle ne prend qu’un
seul argument.
La « valeur » de retour d’une fonction n’a pas nécessairement besoin
d’être numérique (comme celle de sqrt()), et elle n’a pas
non plus besoin d’être un seul élément : elle peut être un ensemble
d’éléments, voire un jeu de données. Nous verrons cela lorsque nous
lirons des fichiers de données dans R.
Les arguments peuvent être n’importe quoi, et non seulement des nombres ou des noms de fichiers, mais aussi d’autres objets. La signification exacte de chaque argument varie selon la fonction et doit être consultée dans la documentation (voir ci-dessous). Certaines fonctions acceptent des arguments qui peuvent être spécifiés par l’utilisateur ou, s’ils sont omis, prendre une valeur par défaut : ceux-ci sont appelés options. Les options sont généralement utilisées pour modifier le mode de fonctionnement de la fonction, par exemple pour déterminer si elle ignore les « valeurs erronées » ou quel symbole utiliser dans un graphique. Cependant, si vous souhaitez quelque chose de spécifique, vous pouvez spécifier une valeur de votre choix qui sera utilisée à la place de la valeur par défaut.
Essayons une fonction capable de prendre plusieurs arguments :
round().
R
round(3.14159)
OUTPUT
[1] 3
Ici, nous avons appelé round() avec un seul argument,
3.14159, et celui-ci a renvoyé la valeur 3.
C’est parce que la valeur par défaut consiste à arrondir au nombre
entier le plus proche. Si nous souhaitons obtenir plus de chiffres, nous
pouvons voir comment faire en obtenant des informations sur la fonction
round. Nous pouvons utiliser args(round) ou
consulter l’aide de cette fonction via ?round.
R
args(round)
OUTPUT
function (x, digits = 0, ...)
NULL
R
?round
On voit que si l’on souhaite un nombre de chiffres différent, on peut
saisir digits=2 ou le nombre souhaité.
R
round(3.14159, digits = 2)
OUTPUT
[1] 3.14
Si vous fournissez les arguments exactement dans le même ordre que celui utilisé pour leur définition, vous n’avez pas besoin de les nommer :
R
round(3.14159, 2)
OUTPUT
[1] 3.14
Et si vous nommez les arguments, vous pouvez en changer l’ordre :
R
round(digits = 2, x = 3.14159)
OUTPUT
[1] 3.14
Il est recommandé de placer les arguments obligatoires (comme le nombre que vous arrondissez) en premier dans votre appel de fonction, et de spécifier le nom de tous les arguments optionnels. Sinon, quelqu’un lisant votre code pourrait devoir consulter la définition d’une fonction présentant des arguments inconnus pour comprendre ce que vous faites. En spécifiant le nom des arguments, vous vous préservez également contre d’éventuels changements futurs de l’interface de la fonction, qui pourraient potentiellement ajouter de nouveaux arguments entre ceux existants.
Vecteurs et types de données
Un vecteur est le type de données le plus courant et le plus basique
dans R, et constitue pratiquement l’outil de base de R. Un vecteur est
composé d’une série de valeurs, telles que des nombres ou des
caractères. Nous pouvons attribuer une série de valeurs à un vecteur à
l’aide de la fonction c(). Par exemple, nous pouvons créer
un vecteur de poids d’animaux et l’attribuer à un nouvel objet
weight_g :
R
weight_g <- c(50, 60, 65, 82)
weight_g
OUTPUT
[1] 50 60 65 82
Un vecteur peut également contenir des caractères :
R
molecules <- c("dna", "rna", "protein")
molecules
OUTPUT
[1] "dna" "rna" "protein"
Les guillemets autour de « dna », « rna », etc., sont indispensables
ici. Sans les guillemets, R supposera qu’il existe des objets nommés
dna, rna et protein. Comme ces
objets n’existent pas dans la mémoire de R, un message d’erreur
s’affichera.
Il existe de nombreuses fonctions qui vous permettent d’examiner le
contenu d’un vecteur. length() vous indique combien
d’éléments se trouvent dans un vecteur particulier :
R
length(weight_g)
OUTPUT
[1] 4
R
length(molecules)
OUTPUT
[1] 3
Une caractéristique importante d’un vecteur est que tous ses éléments
sont du même type de données. La fonction class() indique
la classe (le type d’élément) d’un objet :
R
class(weight_g)
OUTPUT
[1] "numeric"
R
class(molecules)
OUTPUT
[1] "character"
La fonction str() fournit un aperçu de la structure d’un
objet et de ses éléments. C’est une fonction utile lorsque l’on
travaille avec des objets volumineux et complexes :
R
str(weight_g)
OUTPUT
num [1:4] 50 60 65 82
R
str(molecules)
OUTPUT
chr [1:3] "dna" "rna" "protein"
Vous pouvez utiliser la fonction c() pour ajouter
d’autres éléments à votre vecteur :
R
weight_g <- c(weight_g, 90) # add to the end of the vector
weight_g <- c(30, weight_g) # add to the beginning of the vector
weight_g
OUTPUT
[1] 30 50 60 65 82 90
Dans la première ligne, nous prenons le vecteur d’origine
weight_g, ajoutons la valeur 90 à sa fin et
enregistrons le résultat dans weight_g. Ensuite, nous
ajoutons la valeur 30 au début, enregistrant à nouveau le
résultat dans weight_g.
Nous pouvons répéter cette opération à plusieurs reprises pour agrandir un vecteur ou assembler un jeu de données. Lors de la programmation, cela peut s’avérer utile pour ajouter des résultats que nous recueillons ou calculons.
Un vecteur atomique est le type de
données R le plus simple et constitue un vecteur linéaire d’un
seul type. Plus haut, nous avons vu 2 des 6 principaux types de
vecteurs atomiques utilisés par R :
"character" et "numeric" (ou
"double"). Ce sont les éléments de base à partir desquels
sont construits tous les objets R. Les 4 autres types de
vecteurs atomiques sont :
-
"logical"pourTRUEetFALSE(le type de données booléen) -
"integer"pour les nombres entiers (par ex.,2L, leLindique à R qu’il s’agit d’un nombre entier) -
"complex"pour représenter des nombres complexes avec partie réelle et partie imaginaire (par ex.,1 + 4i) et c’est tout ce que nous allons dire à leur sujet -
"raw"pour les flux binaires dont nous ne parlerons pas davantage
Vous pouvez vérifier le type de votre vecteur en utilisant la
fonction typeof() et en saisissant votre vecteur comme
argument.
Les vecteurs sont l’une des nombreuses structures de
données utilisées par R. Parmi les autres structures
importantes figurent les listes (list), les matrices
(matrix), les tableaux de données
(data.frame), les facteurs (factor) et les
tableaux (array).
Défi :
Nous avons vu que les vecteurs atomiques peuvent être de type caractère, numérique (ou double), entier et logique. Mais qu’arrive-t-il si nous essayons de mélanger ces types dans un seul vecteur ?
R les convertit implicitement tous au même type
Défi :
Qu’arrivera-t-il dans chacun de ces exemples ? (indice : utilisez
class() pour vérifier le type de données de vos objets et
saisissez leurs noms pour voir ce qui se passe) :
R
num_char <- c(1, 2, 3, "a")
num_logical <- c(1, 2, 3, TRUE, FALSE)
char_logical <- c("a", "b", "c", TRUE)
tricky <- c(1, 2, 3, "4")
R
class(num_char)
OUTPUT
[1] "character"
R
num_char
OUTPUT
[1] "1" "2" "3" "a"
R
class(num_logical)
OUTPUT
[1] "numeric"
R
num_logical
OUTPUT
[1] 1 2 3 1 0
R
class(char_logical)
OUTPUT
[1] "character"
R
char_logical
OUTPUT
[1] "a" "b" "c" "TRUE"
R
class(tricky)
OUTPUT
[1] "character"
R
tricky
OUTPUT
[1] "1" "2" "3" "4"
Défi :
Pourquoi pensez-vous que cela se produit ?
Les vecteurs ne peuvent contenir qu’un seul type de données. R tente de convertir le contenu de ce vecteur afin de trouver un dénominateur commun qui ne perde aucune information.
Défi :
Combien de valeurs dans combined_logical sont
"TRUE" (en tant que caractère) dans l’exemple suivant :
R
num_logical <- c(1, 2, 3, TRUE)
char_logical <- c("a", "b", "c", TRUE)
combined_logical <- c(num_logical, char_logical)
Un seul. Il n’y a aucune mémoire des types de données antérieurs, et
la coercition s’effectue la première fois que le vecteur est évalué. Par
conséquent, le TRUE dans num_logical est
converti en 1 avant d’être converti en "1"
dans combined_logical.
R
combined_logical
OUTPUT
[1] "1" "2" "3" "1" "a" "b" "c" "TRUE"
Défi :
En R, nous appelons coercion la conversion d’objets d’une classe à une autre. Ces conversions s’effectuent selon une hiérarchie, selon laquelle certains types sont prioritairement convertis en d’autres. Pouvez-vous tracer un schéma représentant la hiérarchie de la manière dont ces types de données sont convertis ?
logique → numérique → caractère ← logique
Extraction de sous-ensembles de vecteurs
Si nous souhaitons extraire une ou plusieurs valeurs d’un vecteur, nous devons fournir un ou plusieurs indices entre crochets. Par exemple :
R
molecules <- c("dna", "rna", "peptide", "protein")
molecules[2]
OUTPUT
[1] "rna"
R
molecules[c(3, 2)]
OUTPUT
[1] "peptide" "rna"
Nous pouvons également répéter les indices pour créer un objet comportant plus d’éléments que l’original :
R
more_molecules <- molecules[c(1, 2, 3, 2, 1, 4)]
more_molecules
OUTPUT
[1] "dna" "rna" "peptide" "rna" "dna" "protein"
Les indices en R commencent à 1. Les langages de programmation tels que Fortran, MATLAB, Julia et R commencent à compter à partir de 1, car c’est ainsi que les êtres humains le font habituellement. Les langages de la famille C (y compris C++, Java, Perl et Python) comptent à partir de 0, car c’est plus simple pour les ordinateurs.
Enfin, il est également possible d’obtenir tous les éléments d’un vecteur, à l’exception de certains éléments spécifiés, en utilisant des indices négatifs :
R
molecules ## all molecules
OUTPUT
[1] "dna" "rna" "peptide" "protein"
R
molecules[-1] ## all but the first one
OUTPUT
[1] "rna" "peptide" "protein"
R
molecules[-c(1, 3)] ## all but 1st/3rd ones
OUTPUT
[1] "rna" "protein"
R
molecules[c(-1, -3)] ## all but 1st/3rd ones
OUTPUT
[1] "rna" "protein"
Sélection conditionnelle d’éléments
Une autre façon courante de sélectionner un sous-ensemble consiste à
utiliser un vecteur logique. TRUE sélectionnera l’élément
ayant le même indice, tandis que FALSE ne le sélectionnera
pas :
R
weight_g <- c(21, 34, 39, 54, 55)
weight_g[c(TRUE, FALSE, TRUE, TRUE, FALSE)]
OUTPUT
[1] 21 39 54
En général, ces vecteurs logiques ne sont pas saisis manuellement, mais sont le résultat d’autres fonctions ou de tests logiques. Par exemple, si vous souhaitiez sélectionner uniquement les valeurs supérieures à 50 :
R
## will return logicals with TRUE for the indices that meet
## the condition
weight_g > 50
OUTPUT
[1] FALSE FALSE FALSE TRUE TRUE
R
## so we can use this to select only the values above 50
weight_g[weight_g > 50]
OUTPUT
[1] 54 55
Vous pouvez combiner plusieurs tests à l’aide de &
(les deux conditions sont vraies, ET) ou de | (au moins
l’une des conditions est vraie, OU) :
R
weight_g[weight_g < 30 | weight_g > 50]
OUTPUT
[1] 21 54 55
R
weight_g[weight_g >= 30 & weight_g == 21]
OUTPUT
numeric(0)
Ici, < désigne « inférieur à », > «
supérieur à », >= « supérieur ou égal à » et
== « égal à ». Le double signe égal == est une
opération de vérification de l’égalité numérique entre le membre de
gauche et celui de droite, et ne doit pas être confondu avec le signe
unique =, qui effectue l’affectation d’une variable (à
l’instar de <-).
Une tâche courante consiste à rechercher certaines chaînes de
caractères dans un vecteur. On pourrait utiliser l’opérateur « ou »
| pour vérifier l’égalité avec plusieurs valeurs, mais cela
peut rapidement devenir fastidieux. La fonction %in% permet
de vérifier si l’un des éléments d’un vecteur de recherche est trouvé
:
R
molecules <- c("dna", "rna", "protein", "peptide")
molecules[molecules == "rna" | molecules == "dna"] # returns both rna and dna
OUTPUT
[1] "dna" "rna"
R
molecules %in% c("rna", "dna", "metabolite", "peptide", "glycerol")
OUTPUT
[1] TRUE TRUE FALSE TRUE
R
molecules[molecules %in% c("rna", "dna", "metabolite", "peptide", "glycerol")]
OUTPUT
[1] "dna" "rna" "peptide"
Défi :
Parvenez-vous à comprendre pourquoi "four" > "five"
renvoie TRUE ?
R
"four" > "five"
OUTPUT
[1] TRUE
Lorsqu’on utilise > ou < sur des
chaînes de caractères, R compare leur ordre alphabétique. Ici,
"four" vient après "five" et lui est donc
supérieur.
Noms
Il est possible de nommer chaque élément d’un vecteur. Le bloc de code ci-dessous montre un vecteur initial sans aucun nom, ainsi que la manière dont les noms sont définis et récupérés.
R
x <- c(1, 5, 3, 5, 10)
names(x) ## no names
OUTPUT
NULL
R
names(x) <- c("A", "B", "C", "D", "E")
names(x) ## now we have names
OUTPUT
[1] "A" "B" "C" "D" "E"
Lorsqu’un vecteur possède des noms, il est possible d’accéder aux éléments par leur nom, en plus de leur index.
R
x[c(1, 3)]
OUTPUT
A C
1 3
R
x[c("A", "C")]
OUTPUT
A C
1 3
Données manquantes
Comme R a été conçu pour analyser des jeux de données, il inclut le
concept de données manquantes (ce qui est rare dans d’autres langages de
programmation). Les données manquantes sont représentées dans les
vecteurs par NA.
Lorsque vous effectuez des opérations sur des nombres, la plupart des
fonctions renvoient NA si les données avec lesquelles vous
travaillez contiennent des valeurs manquantes. Cette fonctionnalité rend
plus difficile le fait de négliger les cas où vous manipulez des données
manquantes. Vous pouvez ajouter l’argument na.rm = TRUE
pour calculer le résultat tout en ignorant les valeurs manquantes.
R
heights <- c(2, 4, 4, NA, 6)
mean(heights)
OUTPUT
[1] NA
R
max(heights)
OUTPUT
[1] NA
R
mean(heights, na.rm = TRUE)
OUTPUT
[1] 4
R
max(heights, na.rm = TRUE)
OUTPUT
[1] 6
Si vos données contiennent des valeurs manquantes, vous souhaiterez
peut-être vous familiariser avec les fonctions is.na(),
na.omit() et complete.cases(). Consultez les
exemples ci-dessous.
R
## Extract those elements which are not missing values.
heights[!is.na(heights)]
OUTPUT
[1] 2 4 4 6
R
## Returns the object with incomplete cases removed.
## The returned object is an atomic vector of type `"numeric"`
## (or `"double"`).
na.omit(heights)
OUTPUT
[1] 2 4 4 6
attr(,"na.action")
[1] 4
attr(,"class")
[1] "omit"
R
## Extract those elements which are complete cases.
## The returned object is an atomic vector of type `"numeric"`
## (or `"double"`).
heights[complete.cases(heights)]
OUTPUT
[1] 2 4 4 6
Défi :
- À l’aide de ce vecteur de tailles en pouces, créez un nouveau vecteur dont les valeurs NA ont été supprimées.
R
heights <- c(63, 69, 60, 65, NA, 68, 61, 70, 61, 59, 64, 69, 63, 63, NA, 72, 65, 64, 70, 63, 65)
- Utilisez la fonction
median()pour calculer la médiane du vecteurheights. - Utilisez R pour déterminer combien de personnes dans l’ensemble mesurent plus de 67 pouces.
R
heights_no_na <- heights[!is.na(heights)]
## or
heights_no_na <- na.omit(heights)
R
median(heights, na.rm = TRUE)
OUTPUT
[1] 64
R
heights_above_67 <- heights_no_na[heights_no_na > 67]
length(heights_above_67)
OUTPUT
[1] 6
Génération de vecteurs
Constructeurs
Il existe plusieurs fonctions permettant de générer des vecteurs de
différents types. Pour générer un vecteur de nombres, on peut utiliser
le constructeur numeric(), en fournissant la longueur du
vecteur de sortie comme paramètre. Les valeurs seront initialisées à
0.
R
numeric(3)
OUTPUT
[1] 0 0 0
R
numeric(10)
OUTPUT
[1] 0 0 0 0 0 0 0 0 0 0
Notons que si nous demandons un vecteur numérique de longueur 0, nous obtenons exactement cela :
R
numeric(0)
OUTPUT
numeric(0)
Il existe des constructeurs similaires pour les caractères et les
valeurs logiques, nommés respectivement character() et
logical().
Défi :
Quelles sont les valeurs par défaut pour les vecteurs de caractères et logiques ?
R
character(2) ## the empty character
OUTPUT
[1] "" ""
R
logical(2) ## FALSE
OUTPUT
[1] FALSE FALSE
Répliquer des éléments
La fonction rep permet de répéter une valeur un certain
nombre de fois. Si nous souhaitons initialiser un vecteur numérique de
longueur 5 avec la valeur -1, par exemple, nous pourrions procéder comme
suit :
R
rep(-1, 5)
OUTPUT
[1] -1 -1 -1 -1 -1
De même, pour générer un vecteur rempli de valeurs manquantes, ce qui constitue souvent un bon point de départ, sans formuler d’hypothèses sur les données à collecter :
R
rep(NA, 5)
OUTPUT
[1] NA NA NA NA NA
rep peut accepter en entrée des vecteurs de longueur
quelconque (ci-dessus, nous avons utilisé des vecteurs de longueur 1) et
de tout type. Par exemple, si nous voulons répéter les valeurs 1, 2 et 3
cinq fois, nous procéderions comme suit :
R
rep(c(1, 2, 3), 5)
OUTPUT
[1] 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3
Défi :
Et si nous voulions répéter les valeurs 1, 2 et 3 cinq fois, mais
obtenir cinq 1, cinq 2 et cinq 3 dans cet ordre ? Il existe deux
possibilités — consultez ?rep ou ?sort pour
obtenir de l’aide.
R
rep(c(1, 2, 3), each = 5)
OUTPUT
[1] 1 1 1 1 1 2 2 2 2 2 3 3 3 3 3
R
sort(rep(c(1, 2, 3), 5))
OUTPUT
[1] 1 1 1 1 1 2 2 2 2 2 3 3 3 3 3
Génération de séquences
Une autre fonction très utile est seq, pour générer une
suite de nombres. Par exemple, pour générer une suite d’entiers de 1 à
20 par paliers de 2, on utiliserait :
R
seq(from = 1, to = 20, by = 2)
OUTPUT
[1] 1 3 5 7 9 11 13 15 17 19
La valeur par défaut de by est 1 et, étant donné que la
génération d’une suite allant d’une valeur à une autre par paliers de 1
est fréquemment utilisée, il existe un raccourci :
R
seq(1, 5, 1)
OUTPUT
[1] 1 2 3 4 5
R
seq(1, 5) ## default by
OUTPUT
[1] 1 2 3 4 5
R
1:5
OUTPUT
[1] 1 2 3 4 5
Pour générer une suite de nombres de 1 à 20 d’une longueur finale de 3, on utiliserait :
R
seq(from = 1, to = 20, length.out = 3)
OUTPUT
[1] 1.0 10.5 20.0
Échantillons aléatoires et permutations
Un dernier groupe de fonctions utiles consiste à génèrer des données
aléatoires. La première, sample, génère une permutation
aléatoire d’un autre vecteur. Par exemple, pour établir un ordre
aléatoire pour l’examen oral de 10 étudiants, j’attribue d’abord à
chaque étudiant un numéro de 1 à 10 (par exemple, selon l’ordre
alphabétique de son nom) puis :
R
sample(1:10)
OUTPUT
[1] 9 4 7 1 2 5 3 10 6 8
Sans arguments supplémentaires, sample renvoie une
permutation de tous les éléments du vecteur. Si je souhaite un
échantillon aléatoire d’une certaine taille, je définirais cette valeur
comme second argument. Ci-dessous, je tire 5 lettres aléatoires de
l’alphabet contenu dans le vecteur letters prédéfini :
R
sample(letters, 5)
OUTPUT
[1] "s" "a" "u" "x" "j"
Si je souhaitais obtenir un échantillon plus long que le vecteur
d’entrée, ou pouvoir tirer certains éléments plusieurs fois, je devrais
fixer l’argument replace à TRUE :
R
sample(1:5, 10, replace = TRUE)
OUTPUT
[1] 2 1 5 5 1 1 5 5 2 2
Défi :
En essayant les fonctions ci-dessus, vous aurez constaté que les
échantillons sont effectivement aléatoires et qu’on n’obtient pas la
même permutation deux fois. Pour pouvoir reproduire ces tirages
aléatoires, on peut définir manuellement la graine de génération de
nombres aléatoires avec set.seed() avant de tirer
l’échantillon aléatoire.
Testez cette fonctionnalité avec votre voisin. Tirez d’abord deux
permutations aléatoires de 1:10 indépendamment et observez
que vous obtenez des résultats différents.
Définissez maintenant la graine avec, par exemple,
set.seed(123) et répétez l’échantillonnage aléatoire.
Observez que vous obtenez désormais les mêmes échantillonnages
aléatoires.
Répétez l’opération en définissant une graine différente.
Différentes permutations
R
sample(1:10)
OUTPUT
[1] 9 1 4 3 6 2 5 8 10 7
R
sample(1:10)
OUTPUT
[1] 4 9 7 6 1 10 8 3 2 5
Mêmes permutations avec la graine 123
R
set.seed(123)
sample(1:10)
OUTPUT
[1] 3 10 2 8 6 9 1 7 5 4
R
set.seed(123)
sample(1:10)
OUTPUT
[1] 3 10 2 8 6 9 1 7 5 4
Une graine différente
R
set.seed(1)
sample(1:10)
OUTPUT
[1] 9 4 7 1 2 5 3 10 6 8
R
set.seed(1)
sample(1:10)
OUTPUT
[1] 9 4 7 1 2 5 3 10 6 8
Tirage d’échantillons à partir d’une distribution normale
La dernière fonction que nous allons voir est rnorm, qui
tire un échantillon aléatoire d’une distribution normale. Deux
distributions normales dont les moyennes sont 0 et 100 et les
écarts-types 1 et 5, notées N(0, 1) et N(100, 5), sont
illustrées ci-dessous.

Les trois arguments, n, mean et
sd, définissent la taille de l’échantillon ainsi que les
paramètres de la distribution normale, à savoir sa moyenne et son
écart-type. Les valeurs par défaut de la moyenne et de l’écart-type sont
respectivement 0 et 1.
R
rnorm(5)
OUTPUT
[1] 0.69641761 0.05351568 -1.31028350 -2.12306606 -0.20807859
R
rnorm(5, 2, 2)
OUTPUT
[1] 1.3744268 -0.1164714 2.8344472 1.3690969 3.6510983
R
rnorm(5, 100, 5)
OUTPUT
[1] 106.45636 96.87448 95.62427 100.71678 107.12595
Maintenant que nous avons appris à écrire des scripts et les bases des structures de données de R, nous sommes prêts à commencer à travailler avec des données plus volumineuses et à découvrir les tableaux de données.
- Comment interagir avec R
Content from Débuts avec les données
Last updated on 2026-11-07 | Edit this page
Estimated time: 60 minutes
Overview
Questions
- Première analyse de données dans R
Objectives
- Décrivez ce qu’est un
data.frame. - Charger des données externes depuis un fichier .csv dans un tableau de données.
- Résumer le contenu d’un tableau de données.
- Décrivez ce qu’est un facteur.
- Convertir entre chaînes de caractères et facteurs.
- Réordonner et renommer les facteurs.
- Formater les dates.
- Exporter et enregistrer les données.
Cet épisode est basé sur la leçon Data Analysis and Visualisation in R for Ecologists de Data Carpentries.
Présentation des données d’expression génique
Nous allons utiliser une partie des données publiées par Blackmore et al. (2017), The effect of upper-respiratory infection on transcriptomic changes in the CNS. L’objectif de l’étude était de déterminer l’effet d’une infection des voies respiratoires supérieures sur les modifications de la transcription de l’ARN dans le cervelet et la moelle épinière après l’infection. Des souris C57BL/6 âgées de huit semaines et appariées selon le sexe ont reçu, par voie intranasale, du sérum physiologique ou le virus de la grippe A. Les modifications transcriptomiques dans les tissus du cervelet et de la moelle épinière ont été évaluées par RNA-seq aux jours 0 (souris non infectées), 4 et 8.
L’ensemble de données est stocké sous la forme d’un fichier de valeurs séparées par des virgules (CSV). Chaque ligne contient des informations concernant une seule mesure d’expression ARN, et les onze premières colonnes représentent :
| Colonne | Description |
|---|---|
| gene | Le nom du gène mesuré |
| sample | Le nom de l’échantillon dans lequel l’expression génique a été mesurée |
| expression | La valeur de l’expression génique |
| organism | L’organisme/l’espèce - ici, toutes les données proviennent de souris |
| age | L’âge de la souris (ici, toutes les souris avaient 8 semaines) |
| sex | Le sexe de la souris |
| infection | L’état infectieux de la souris, c’est-à-dire infectée par le virus de la grippe A ou non infectée. |
| strain | La souche du virus de la grippe A. |
| time | La durée de l’infection (en jours). |
| tissue | Le tissu utilisé pour l’expérience d’expression génique, c’est-à-dire le cervelet ou la moelle épinière. |
| mouse | L’identifiant unique de la souris. |
Nous allons utiliser la fonction R download.file() pour
télécharger le fichier CSV contenant les données d’expression génique,
et nous utiliserons read.csv() pour charger dans la mémoire
le contenu du fichier CSV sous la forme d’un objet de classe
data.frame. Dans la commande download.file, la
première entrée est une chaîne de caractères contenant l’URL de la
source. Cette URL de source télécharge un fichier CSV depuis un dépôt
GitHub. Le texte après la virgule ("data/rnaseq.csv")
correspond à la destination du fichier sur votre machine locale. Vous
devrez disposer d’un dossier sur votre machine nommé "data"
où vous téléchargerez le fichier. Ainsi, cette commande télécharge le
fichier distant, le nomme "rnaseq.csv" et l’ajoute à un
dossier déjà existant nommé "data".
R
download.file(url = "https://github.com/carpentries-incubator/bioc-intro/raw/main/episodes/data/rnaseq.csv",
destfile = "data/rnaseq.csv")
Vous êtes désormais prêt à charger les données :
R
rna <- read.csv("data/rnaseq.csv")
Cette instruction ne produit aucun résultat car, comme vous vous en souvenez peut-être, les affectations n’affichent rien. Si nous voulons vérifier que nos données ont été chargées, nous pouvons consulter le contenu du tableau de données en saisissant son nom :
R
rna
Waouh… c’était beaucoup de résultats. Au moins, cela signifie que les
données ont été chargées correctement. Vérifions le début (les 6
premières lignes) de ce tableau de données à l’aide de la fonction
head() :
R
head(rna)
OUTPUT
gene sample expression organism age sex infection strain time
1 Asl GSM2545336 1170 Mus musculus 8 Female InfluenzaA C57BL/6 8
2 Apod GSM2545336 36194 Mus musculus 8 Female InfluenzaA C57BL/6 8
3 Cyp2d22 GSM2545336 4060 Mus musculus 8 Female InfluenzaA C57BL/6 8
4 Klk6 GSM2545336 287 Mus musculus 8 Female InfluenzaA C57BL/6 8
5 Fcrls GSM2545336 85 Mus musculus 8 Female InfluenzaA C57BL/6 8
6 Slc2a4 GSM2545336 782 Mus musculus 8 Female InfluenzaA C57BL/6 8
tissue mouse ENTREZID
1 Cerebellum 14 109900
2 Cerebellum 14 11815
3 Cerebellum 14 56448
4 Cerebellum 14 19144
5 Cerebellum 14 80891
6 Cerebellum 14 20528
product
1 argininosuccinate lyase, transcript variant X1
2 apolipoprotein D, transcript variant 3
3 cytochrome P450, family 2, subfamily d, polypeptide 22, transcript variant 2
4 kallikrein related-peptidase 6, transcript variant 2
5 Fc receptor-like S, scavenger receptor, transcript variant X1
6 solute carrier family 2 (facilitated glucose transporter), member 4
ensembl_gene_id external_synonym chromosome_name gene_biotype
1 ENSMUSG00000025533 2510006M18Rik 5 protein_coding
2 ENSMUSG00000022548 <NA> 16 protein_coding
3 ENSMUSG00000061740 2D22 15 protein_coding
4 ENSMUSG00000050063 Bssp 7 protein_coding
5 ENSMUSG00000015852 2810439C17Rik 3 protein_coding
6 ENSMUSG00000018566 Glut-4 11 protein_coding
phenotype_description
1 abnormal circulating amino acid level
2 abnormal lipid homeostasis
3 abnormal skin morphology
4 abnormal cytokine level
5 decreased CD8-positive alpha-beta T cell number
6 abnormal circulating glucose level
hsapiens_homolog_associated_gene_name
1 ASL
2 APOD
3 CYP2D6
4 KLK6
5 FCRL2
6 SLC2A4
R
## Try also
## View(rna)
Note
read.csv() suppose que les champs sont séparés par des
virgules ; cependant, dans plusieurs pays, la virgule est utilisée comme
séparateur décimal et le point-virgule (;) comme séparateur de champs.
Si vous souhaitez lire ce type de fichiers dans R, vous pouvez utiliser
la fonction read.csv2(). Elle se comporte exactement comme
read.csv(), mais utilise des paramètres différents pour les
séparateurs décimaux et de champs. Si vous travaillez avec un autre
format, ces deux paramètres peuvent être spécifiés par l’utilisateur.
Consultez l’aide de read.csv() en saisissant
?read.csv pour en savoir plus. Il existe également la
fonction read.delim() pour lire des fichiers de données
séparés par des tabulations. Il est important de noter que toutes ces
fonctions sont en réalité des fonctions wrapper pour la fonction
principale read.table() avec des arguments différents.
Ainsi, les données ci-dessus auraient également pu être chargées en
utilisant read.table() avec le paramètre de séparation
,. Le code est le suivant :
R
rna <- read.table(file = "data/rnaseq.csv",
sep = ",",
header = TRUE)
L’argument header doit être défini à TRUE pour pouvoir lire les
en-têtes, car par défaut, read.table() a l’argument header
défini à FALSE.
Qu’est-ce que des tableaux de données ?
Les tableaux de données sont la structure de données de facto pour la plupart des données tabulaires, et ce que nous utilisons pour la statistique et la représentation graphique.
Un tableau de données peut être créé manuellement, mais il est le
plus souvent généré par les fonctions read.csv() ou
read.table() ; en d’autres termes, lors de l’importation de
feuilles de calcul depuis votre disque dur (ou le Web).
Un tableau de données est la représentation de données sous la forme d’un tableau où les colonnes sont des vecteurs de longueur identique. Comme les colonnes sont des vecteurs, chacune d’elles doit contenir un seul type de données (par exemple, des caractères, des entiers, des facteurs). Voici, par exemple, une figure illustrant un tableau de données comprenant un vecteur numérique, un vecteur de caractères et un vecteur logique.
Nous pouvons le constater en examinant la structure d’un
tableau de données avec la fonction str() :
R
str(rna)
OUTPUT
'data.frame': 32428 obs. of 19 variables:
$ gene : chr "Asl" "Apod" "Cyp2d22" "Klk6" ...
$ sample : chr "GSM2545336" "GSM2545336" "GSM2545336" "GSM2545336" ...
$ expression : int 1170 36194 4060 287 85 782 1619 288 43217 1071 ...
$ organism : chr "Mus musculus" "Mus musculus" "Mus musculus" "Mus musculus" ...
$ age : int 8 8 8 8 8 8 8 8 8 8 ...
$ sex : chr "Female" "Female" "Female" "Female" ...
$ infection : chr "InfluenzaA" "InfluenzaA" "InfluenzaA" "InfluenzaA" ...
$ strain : chr "C57BL/6" "C57BL/6" "C57BL/6" "C57BL/6" ...
$ time : int 8 8 8 8 8 8 8 8 8 8 ...
$ tissue : chr "Cerebellum" "Cerebellum" "Cerebellum" "Cerebellum" ...
$ mouse : int 14 14 14 14 14 14 14 14 14 14 ...
$ ENTREZID : int 109900 11815 56448 19144 80891 20528 97827 118454 18823 14696 ...
$ product : chr "argininosuccinate lyase, transcript variant X1" "apolipoprotein D, transcript variant 3" "cytochrome P450, family 2, subfamily d, polypeptide 22, transcript variant 2" "kallikrein related-peptidase 6, transcript variant 2" ...
$ ensembl_gene_id : chr "ENSMUSG00000025533" "ENSMUSG00000022548" "ENSMUSG00000061740" "ENSMUSG00000050063" ...
$ external_synonym : chr "2510006M18Rik" NA "2D22" "Bssp" ...
$ chromosome_name : chr "5" "16" "15" "7" ...
$ gene_biotype : chr "protein_coding" "protein_coding" "protein_coding" "protein_coding" ...
$ phenotype_description : chr "abnormal circulating amino acid level" "abnormal lipid homeostasis" "abnormal skin morphology" "abnormal cytokine level" ...
$ hsapiens_homolog_associated_gene_name: chr "ASL" "APOD" "CYP2D6" "KLK6" ...
Inspection des objets data.frame
Nous avons déjà vu comment les fonctions head() et
str() peuvent être utiles pour vérifier le contenu et la
structure d’un tableau de données. Voici une liste non exhaustive de
fonctions permettant de se faire une idée du contenu et de la structure
des données. Essayons-les !
Taille :
-
dim(rna)- retourne un vecteur dont le premier élément est le nombre de lignes et le second le nombre de colonnes (les dimensions de l’objet). -
nrow(rna)- renvoie le nombre de lignes. -
ncol(rna)- renvoie le nombre de colonnes.
Contenu :
-
head(rna)- affiche les 6 premières lignes. -
tail(rna)- affiche les 6 dernières lignes.
Noms :
-
names(rna)- renvoie les noms des colonnes (synonyme decolnames()pour les objetsdata.frame). -
rownames(rna)- renvoie les noms de lignes.
Résumé :
-
str(rna)- structure de l’objet et informations sur la classe, la longueur et le contenu de chaque colonne. -
summary(rna)- statistiques de synthèse pour chaque colonne.
Note : la plupart de ces fonctions sont « génériques » ; elles
peuvent être utilisées sur d’autres types d’objets en plus de
data.frame.
Défi :
Sur la base de la sortie de str(rna), pouvez-vous
répondre aux questions suivantes ?
- Quelle est la classe de l’objet
rna? - Combien y a-t-il de lignes et de colonnes dans cet objet ?
- classe : tableau de données
- nombre de lignes : 32428, nombre de colonnes : 19
Indexation et extraction de sous-ensembles de tableaux de données
Notre tableau de données rna possède des lignes et des
colonnes (il a 2 dimensions) ; si nous souhaitons en extraire certaines
données spécifiques, nous devons spécifier les « coordonnées »
souhaitées. Les numéros de ligne viennent en premier, suivis des numéros
de colonne. Notez toutefois que différentes manières de spécifier ces
coordonnées donnent des résultats de classes différentes.
R
# first element in the first column of the data frame (as a vector)
rna[1, 1]
# first element in the 6th column (as a vector)
rna[1, 6]
# first column of the data frame (as a vector)
rna[, 1]
# first column of the data frame (as a data.frame)
rna[1]
# first three elements in the 7th column (as a vector)
rna[1:3, 7]
# the 3rd row of the data frame (as a data.frame)
rna[3, ]
# equivalent to head_rna <- head(rna)
head_rna <- rna[1:6, ]
head_rna
: est une fonction spéciale qui crée des vecteurs
numériques d’entiers en ordre croissant ou décroissant ; voyez par
exemple 1:10 et 10:1. Consultez la section Génération de vecteurs
pour plus de détails.
Vous pouvez également exclure certains indices d’un tableau de
données en utilisant le signe « - » :
R
rna[, -1] ## The whole data frame, except the first column
rna[-c(7:66465), ] ## Equivalent to head(rna)
On peut extraire des sous-ensembles de tableaux de données en utilisant des indices (comme illustré précédemment), mais aussi directement les noms des colonnes :
R
rna["gene"] # Result is a data.frame
rna[, "gene"] # Result is a vector
rna[["gene"]] # Result is a vector
rna$gene # Result is a vector
Dans RStudio, vous pouvez utiliser la fonctionnalité d’autocomplétion pour obtenir les noms complets et corrects des colonnes.
Défi
Créez un
data.frame(rna_200) contenant uniquement les données de la ligne 200 du jeu de donnéesrna.Remarquez comment
nrow()vous a donné le nombre de lignes dans undata.frame?
Utilisez ce nombre pour extraire uniquement cette dernière ligne du tableau de données initial
rna.Comparez cela avec ce que vous voyez comme la dernière ligne à l’aide de
tail()pour vous assurer que cela correspond aux attentes.Extrayez cette dernière ligne en utilisant
nrow()au lieu du numéro de ligne.Créez un nouveau tableau de données (
rna_last) à partir de cette dernière ligne.
Utilisez
nrow()pour extraire la ligne située au milieu du tableau de donnéesrna. Stockez le contenu de cette ligne dans un objet nommérna_middle.Combinez
nrow()avec la notation-ci-dessus pour reproduire le comportement dehead(rna), en ne gardant que les premières 6 lignes du jeu de données rna.
R
## 1.
rna_200 <- rna[200, ]
## 2.
## Saving `n_rows` to improve readability and reduce duplication
n_rows <- nrow(rna)
rna_last <- rna[n_rows, ]
## 3.
rna_middle <- rna[n_rows / 2, ]
## 4.
rna_head <- rna[-(7:n_rows), ]
Facteurs
Les facteurs représentent des données catégorielles. Ils sont stockés sous forme d’entiers associés à des étiquettes et peuvent être ordonnés ou non. Bien que les facteurs ressemblent (et se comportent souvent) à des vecteurs de caractères, ils sont en réalité traités comme des vecteurs entiers par R. Il faut donc être très prudent lorsque l’on les traite comme des chaînes de caractères.
Une fois créés, les facteurs ne peuvent contenir qu’un ensemble prédéfini de valeurs, appelées niveaux. Par défaut, R trie toujours les niveaux par ordre alphabétique. Par exemple, si vous avez un facteur avec 2 niveaux :
R
sex <- factor(c("male", "female", "female", "male", "female"))
R attribuera 1 au niveau "female" et
2 au niveau "male" (car f précède
m, même si le premier élément de ce vecteur est
"male"). Vous pouvez vérifier cela en utilisant la fonction
levels() et vous pouvez trouver le nombre de niveaux à
l’aide de nlevels() :
R
levels(sex)
OUTPUT
[1] "female" "male"
R
nlevels(sex)
OUTPUT
[1] 2
Parfois, l’ordre des facteurs n’a aucune importance ; d’autres fois,
vous souhaiterez peut-être en spécifier l’ordre car celui-ci a un sens
(par ex. « low », « medium », « high »), car il améliore votre
visualisation ou parce qu’il est requis par un type d’analyse
particulier. Ici, l’un des moyens de réordonner nos niveaux dans le
vecteur sex serait :
R
sex ## current order
OUTPUT
[1] male female female male female
Levels: female male
R
sex <- factor(sex, levels = c("male", "female"))
sex ## after re-ordering
OUTPUT
[1] male female female male female
Levels: male female
Dans la mémoire de R, ces facteurs sont représentés par des entiers
(1, 2, 3), mais ils sont plus informatifs que les entiers car les
facteurs sont auto-descriptifs : "female",
"male" est plus descriptif que 1,
2. Lequel est « mâle » ? Vous ne pourriez pas le déterminer
uniquement à partir des données entières. Les facteurs, en revanche,
intègrent cette information. Cela est particulièrement utile lorsqu’il y
a de nombreux niveaux (comme le biotype génique dans notre jeu de
données d’exemple).
Lorsque vos données sont stockées sous forme de facteur, vous pouvez
utiliser la fonction plot() pour obtenir un aperçu rapide
du nombre d’observations représentées par chaque niveau de facteur.
Examinons le nombre de mâles et de femelles dans nos données.
R
plot(sex)

Conversion en chaîne de caractères
Si vous devez convertir un facteur en vecteur de caractères, vous
utilisez as.character(x).
R
as.character(sex)
OUTPUT
[1] "male" "female" "female" "male" "female"
Renommage des facteurs
Si nous souhaitons renommer ce facteur, il suffit de modifier ses niveaux :
R
levels(sex)
OUTPUT
[1] "male" "female"
R
levels(sex) <- c("M", "F")
sex
OUTPUT
[1] M F F M F
Levels: M F
R
plot(sex)

Défi :
- Remplacez « F » et « M » par « Female » et « Male » respectivement.
R
levels(sex)
OUTPUT
[1] "M" "F"
R
levels(sex) <- c("Male", "Female")
Défi :
Nous avons vu comment créer des tableaux de données en utilisant
read.csv(), mais ils peuvent également être créés
manuellement avec la fonction data.frame(). Il y a quelques
erreurs dans ce data.frame conçu à la main. Pouvez-vous les
repérer et les corriger ? N’hésitez pas à expérimenter !
- absence de guillemets autour des noms des animaux
- une entrée manquante dans la colonne « feel » (probablement pour l’un des animaux à poils)
- une virgule manquante dans la colonne du poids
Défi :
Pouvez-vous prédire la classe de chacune des colonnes dans l’exemple suivant ?
Vérifiez vos conjectures à l’aide de
str(country_climate) :
Sont-elles ce que vous attendiez ? Pourquoi ? Pourquoi pas ?
Réessayez en ajoutant
stringsAsFactors = TRUEaprès la dernière variable lors de la création du tableau de données. Que se passe-t-il maintenant ?stringsAsFactorspeut également être défini lors de la lecture de feuilles de calcul textuelles dans R à l’aide deread.csv().
R
country_climate <- data.frame(
country = c("Canada", "Panama", "South Africa", "Australia"),
climate = c("cold", "hot", "temperate", "hot/temperate"),
temperature = c(10, 30, 18, "15"),
northern_hemisphere = c(TRUE, TRUE, FALSE, "FALSE"),
has_kangaroo = c(FALSE, FALSE, FALSE, 1)
)
R
country_climate <- data.frame(
country = c("Canada", "Panama", "South Africa", "Australia"),
climate = c("cold", "hot", "temperate", "hot/temperate"),
temperature = c(10, 30, 18, "15"),
northern_hemisphere = c(TRUE, TRUE, FALSE, "FALSE"),
has_kangaroo = c(FALSE, FALSE, FALSE, 1)
)
str(country_climate)
OUTPUT
'data.frame': 4 obs. of 5 variables:
$ country : chr "Canada" "Panama" "South Africa" "Australia"
$ climate : chr "cold" "hot" "temperate" "hot/temperate"
$ temperature : chr "10" "30" "18" "15"
$ northern_hemisphere: chr "TRUE" "TRUE" "FALSE" "FALSE"
$ has_kangaroo : num 0 0 0 1
La conversion automatique du type de données est parfois une chance, parfois une source de frustration. Sachez qu’elle existe, apprenez les règles et vérifiez à nouveau que les données que vous importez dans R sont du type correct au sein de votre tableau de données. Si ce n’est pas le cas, utilisez-la à votre avantage pour détecter des erreurs qui auraient pu être introduites lors de la saisie des données (par exemple, une lettre dans une colonne qui ne devrait contenir que des nombres).
En savoir plus dans ce tutoriel RStudio
Matrices
Avant de poursuivre, maintenant que nous avons découvert les tableaux
de données, rappelons l’installation des packages et apprenons un
nouveau type de données, à savoir le matrix. Comme le
data.frame, une matrice possède deux dimensions : des
lignes et des colonnes. Mais la différence majeure est que toutes les
cellules d’une matrix doivent être du même type :
numeric, character, logical, … À
cet égard, les matrices sont plus proches d’un vector que
d’un data.frame.
Le constructeur par défaut pour une matrice est matrix.
Il prend un vecteur de valeurs pour remplir la matrice ainsi que le
nombre de lignes et/ou de colonnes1. Les valeurs sont disposées colonne par
colonne, comme illustré ci-dessous.
R
m <- matrix(1:9, ncol = 3, nrow = 3)
m
OUTPUT
[,1] [,2] [,3]
[1,] 1 4 7
[2,] 2 5 8
[3,] 3 6 9
Défi :
À l’aide de la fonction installed.packages(), créez une
matrice character contenant les informations sur tous les
packages actuellement installés sur votre ordinateur. Analysez-la.
R
## create the matrix
ip <- installed.packages()
head(ip)
## try also View(ip)
## number of package
nrow(ip)
## names of all installed packages
rownames(ip)
## type of information we have about each package
colnames(ip)
Il est souvent utile de créer de grandes matrices de données
aléatoires pour servir de données de test. L’exercice ci-dessous vous
demande de créer une telle matrice avec des données aléatoires tirées
d’une distribution normale de moyenne 0 et d’écart-type 1, ce qui peut
être réalisé avec la fonction rnorm().
Défi :
Construisez une matrice de 1000 lignes et 3 colonnes contenant des données suivant une loi normale de moyenne 0 et d’écart-type 1.
R
set.seed(123)
m <- matrix(rnorm(3000), ncol = 3)
dim(m)
OUTPUT
[1] 1000 3
R
head(m)
OUTPUT
[,1] [,2] [,3]
[1,] -0.56047565 -0.99579872 -0.5116037
[2,] -0.23017749 -1.03995504 0.2369379
[3,] 1.55870831 -0.01798024 -0.5415892
[4,] 0.07050839 -0.13217513 1.2192276
[5,] 0.12928774 -2.54934277 0.1741359
[6,] 1.71506499 1.04057346 -0.6152683
Mise en forme des dates
L’un des problèmes les plus fréquents rencontrés par les nouveaux utilisateurs de R (ainsi que par les utilisateurs expérimentés !) est la conversion des informations de date et d’heure en une variable appropriée et utilisable lors des analyses.
Note sur les dates dans les logiciels de feuilles de calcul
Les dates dans les feuilles de calcul sont généralement stockées dans une seule colonne. Bien que cela semble être la manière la plus naturelle de consigner les dates, il ne s’agit en réalité pas d’une bonne pratique. Une application de feuille de calcul affichera les dates d’une manière apparemment correcte (pour un observateur humain), mais la façon dont elle gère et stocke réellement les dates peut s’avérer problématique. Il est souvent bien plus sûr de stocker les dates avec l’ANNÉE, le MOIS et le JOUR dans des colonnes distinctes, ou sous la forme d’ANNÉE et de JOUR DE L’ANNÉE dans des colonnes distinctes.
Les logiciels de feuilles de calcul tels que LibreOffice, Microsoft Excel, OpenOffice, Gnumeric, … utilisent des méthodes d’encodage des dates différentes (et souvent incompatibles) (même au sein d’un même logiciel entre les versions et les systèmes d’exploitation). De plus, Excel peut convertir des éléments qui ne sont pas des dates en dates ( Zeeberg et al. (2004) ), par exemple des noms ou des identifiants tels que MAR1, DEC1, OCT4. Ainsi, si vous évitez globalement le format de date, il est plus facile d’identifier ces problèmes.
La section Dates as data de la leçon Data Carpentry apporte des informations complémentaires sur les pièges liés aux dates dans les feuilles de calcul.
Nous allons utiliser la fonction ymd() du package
lubridate (qui appartient au
tidyverse ; en savoir plus sur le site web de tidyverse).
lubridate est installé dans le cadre de
l’installation de tidyverse. Lorsque vous
chargez tidyverse
(library(tidyverse)), les packages principaux (les packages
utilisés dans la plupart des analyses de données) sont chargés.
lubridate ne fait cependant pas partie du
tidyverse principal, vous devez donc le charger explicitement avec
library(lubridate).
Commencez par charger le package requis :
R
library("lubridate")
ymd() prend en entrée un vecteur représentant l’année,
le mois et le jour, et le convertit en vecteur Date.
Date est une classe de données reconnue par R comme étant
une date et peut être manipulée en tant que telle. L’argument requis par
la fonction est flexible, mais, selon les bonnes pratiques, il s’agit
d’un vecteur de caractères formaté sous la forme « YYYY-MM-DD ».
Créons un objet date et examinons sa structure :
R
my_date <- ymd("2015-01-01")
str(my_date)
OUTPUT
Date[1:1], format: "2015-01-01"
Concaténons maintenant l’année, le mois et le jour fournis séparément : nous obtenons le même résultat.
R
# sep indicates the character to use to separate each component
my_date <- ymd(paste("2015", "1", "1", sep = "-"))
str(my_date)
OUTPUT
Date[1:1], format: "2015-01-01"
Familiarisons-nous maintenant avec un pipeline typique de
manipulation de dates. Le petit jeu de données ci-dessous contient des
dates stockées dans des colonnes distinctes year,
month et day.
R
x <- data.frame(year = c(1996, 1992, 1987, 1986, 2000, 1990, 2002, 1994, 1997, 1985),
month = c(2, 3, 3, 10, 1, 8, 3, 4, 5, 5),
day = c(24, 8, 1, 5, 8, 17, 13, 10, 11, 24),
value = c(4, 5, 1, 9, 3, 8, 10, 2, 6, 7))
x
OUTPUT
year month day value
1 1996 2 24 4
2 1992 3 8 5
3 1987 3 1 1
4 1986 10 5 9
5 2000 1 8 3
6 1990 8 17 8
7 2002 3 13 10
8 1994 4 10 2
9 1997 5 11 6
10 1985 5 24 7
Nous appliquons maintenant cette fonction au jeu de données
x. Nous créons d’abord un vecteur de caractères à partir
des colonnes year, month et day
de x en utilisant paste() :
R
paste(x$year, x$month, x$day, sep = "-")
OUTPUT
[1] "1996-2-24" "1992-3-8" "1987-3-1" "1986-10-5" "2000-1-8" "1990-8-17"
[7] "2002-3-13" "1994-4-10" "1997-5-11" "1985-5-24"
Ce vecteur de caractères peut être utilisé comme argument pour
ymd() :
R
ymd(paste(x$year, x$month, x$day, sep = "-"))
OUTPUT
[1] "1996-02-24" "1992-03-08" "1987-03-01" "1986-10-05" "2000-01-08"
[6] "1990-08-17" "2002-03-13" "1994-04-10" "1997-05-11" "1985-05-24"
Le vecteur Date obtenu peut être ajouté à x
sous la forme d’une nouvelle colonne appelée date :
R
x$date <- ymd(paste(x$year, x$month, x$day, sep = "-"))
str(x) # notice the new column, with 'date' as the class
OUTPUT
'data.frame': 10 obs. of 5 variables:
$ year : num 1996 1992 1987 1986 2000 ...
$ month: num 2 3 3 10 1 8 3 4 5 5
$ day : num 24 8 1 5 8 17 13 10 11 24
$ value: num 4 5 1 9 3 8 10 2 6 7
$ date : Date, format: "1996-02-24" "1992-03-08" ...
Vérifions que tout a bien fonctionné. L’un des moyens d’examiner la
nouvelle colonne est d’utiliser summary() :
R
summary(x$date)
OUTPUT
Min. 1st Qu. Median Mean 3rd Qu. Max.
"1985-05-24" "1988-01-11" "1993-03-24" "1993-03-18" "1997-01-20" "2002-03-13"
Notez que ymd() attend l’année, le mois et le jour, dans
cet ordre. Si vous avez, par exemple, le jour, le mois et l’année, vous
aurez besoin de dmy().
R
dmy(paste(x$day, x$month, x$year, sep = "-"))
OUTPUT
[1] "1996-02-24" "1992-03-08" "1987-03-01" "1986-10-05" "2000-01-08"
[6] "1990-08-17" "2002-03-13" "1994-04-10" "1997-05-11" "1985-05-24"
lubdridate dispose de nombreuses fonctions pour gérer
toutes les variations de dates.
Résumé des objets R
Jusqu’à présent, nous avons vu plusieurs types d’objets R, différant par le nombre de dimensions et par le fait qu’ils pouvaient stocker un seul ou plusieurs types de données :
-
vector: une dimension (une longueur), un seul type de données. -
matrix: deux dimensions, un seul type de données. -
data.frame: deux dimensions, un type par colonne.
Listes
Les listes sont un type de données que nous n’avons pas encore vu, mais qu’il est utile de connaître et qui complète le résumé que nous venons de voir :
-
list: une dimension, chaque élément peut être d’un type de données différent.
Ci-dessous, créons une liste contenant un vecteur de nombres, des caractères, une matrice, un tableau de données et une autre liste :
R
l <- list(1:10, ## numeric
letters, ## character
installed.packages(), ## a matrix
cars, ## a data.frame
list(1, 2, 3)) ## a list
length(l)
OUTPUT
[1] 5
R
str(l)
OUTPUT
List of 5
$ : int [1:10] 1 2 3 4 5 6 7 8 9 10
$ : chr [1:26] "a" "b" "c" "d" ...
$ : chr [1:190, 1:17] "abind" "askpass" "assertthat" "backports" ...
..- attr(*, "dimnames")=List of 2
.. ..$ : chr [1:190] "abind" "askpass" "assertthat" "backports" ...
.. ..$ : chr [1:17] "Package" "LibPath" "Version" "Priority" ...
$ :'data.frame': 50 obs. of 2 variables:
..$ speed: num [1:50] 4 4 7 7 8 9 10 10 10 11 ...
..$ dist : num [1:50] 2 10 4 22 16 10 18 26 34 17 ...
$ :List of 3
..$ : num 1
..$ : num 2
..$ : num 3
La sous-sélection de listes s’effectue à l’aide de []
pour créer une nouvelle sous-liste ou de [[]] pour extraire
un seul élément de cette liste (en utilisant des indices ou des noms, si
la liste est nommée).
R
l[[1]] ## first element
OUTPUT
[1] 1 2 3 4 5 6 7 8 9 10
R
l[1:2] ## a list of length 2
OUTPUT
[[1]]
[1] 1 2 3 4 5 6 7 8 9 10
[[2]]
[1] "a" "b" "c" "d" "e" "f" "g" "h" "i" "j" "k" "l" "m" "n" "o" "p" "q" "r" "s"
[20] "t" "u" "v" "w" "x" "y" "z"
R
l[1] ## a list of length 1
OUTPUT
[[1]]
[1] 1 2 3 4 5 6 7 8 9 10
Exportation et sauvegarde de données tabulaires
Nous avons vu comment importer une feuille de calcul textuelle dans R
à l’aide de la famille de fonctions read.table. Pour
exporter un data.frame vers une feuille de calcul
textuelle, nous pouvons utiliser l’ensemble de fonctions
write.table (write.csv,
write.delim, …). Elles prennent toutes en argument la
variable à exporter et le fichier de destination. Par exemple, pour
exporter les données rna vers le fichier
my_rna.csv dans le répertoire data_output,
nous exécuterions :
R
write.csv(rna, file = "data_output/my_rna.csv")
Ce nouveau fichier CSV peut désormais être partagé avec d’autres
collaborateurs qui ne maîtrisent pas R. Notez que, bien qu’il y ait des
virgules dans certains champs du data.frame (voir par
exemple la colonne « product »), R entourera par défaut chaque champ de
guillemets, et nous pourrons donc le lire correctement dans R, malgré
l’utilisation également de virgules comme séparateurs de colonnes.
- Données tabulaires dans R
Le nombre de lignes ou de colonnes suffit, car l’autre peut être déduit de la longueur des valeurs. Essayez de voir ce qui se passe si les valeurs et le nombre de lignes/colonnes ne correspondent pas.↩︎
Content from Manipulation et analyse de données avec dplyr
Last updated on 2026-11-07 | Edit this page
Estimated time: 150 minutes
Overview
Questions
- Analyse de données en R à l’aide du méta-package tidyverse
Objectives
- Décrivez l’objectif des packages
dplyrettidyr. - Décrivez plusieurs de leurs fonctions extrêmement utiles pour manipuler les données.
- Décrivez les concepts de format large et de format long, et voyez comment restructurer un tableau de données d’un format à l’autre.
- Démontrer comment joindre des tables.
Cet épisode est basé sur la leçon Data Analysis and Visualisation in R for Ecologists de Data Carpentries.
Manipulation des données à l’aide de
dplyr et
tidyr
L’extraction de sous-ensembles à l’aide de crochets est pratique, mais elle peut s’avérer fastidieuse et difficile à lire, surtout pour des opérations complexes.
Certains packages peuvent grandement faciliter notre tâche lors de la
manipulation de données. Les packages dans R sont essentiellement des
ensembles de fonctions supplémentaires qui vous permettent d’en faire
davantage. Les fonctions que nous avons utilisées jusqu’à présent, comme
str() ou data.frame(), sont intégrées à R ; le
chargement de packages peut vous donner accès à d’autres fonctions
spécifiques. Avant d’utiliser un package pour la première fois, vous
devez l’installer sur votre machine, puis vous devez l’importer à chaque
session R ultérieure lorsque vous en avez besoin.
Le package
dplyrpropose des outils puissants pour les tâches de manipulation de données. Il est conçu pour fonctionner directement avec des tableaux de données, avec de nombreuses opérations de manipulation optimisées.Comme nous le verrons plus loin, il arrive que nous souhaitions restructurer un tableau de données afin de pouvoir effectuer certaines analyses spécifiques ou pour la visualisation. Le package
tidyrrépond à ce problème courant de restructuration des données et propose des outils pour manipuler les données de manière ordonnée.
Pour en savoir plus sur dplyr et
tidyr après l’atelier, vous souhaiterez
peut-être consulter cette fiche
pratique sur la transformation de données avec
dplyr et celle-ci sur
tidyr.
- Le package
tidyverseest un « package parapluie » qui installe plusieurs packages utiles pour l’analyse de données qui fonctionnent bien ensemble, tels quetidyr,dplyr,ggplot2,tibble, etc. Ces packages nous aident à travailler avec les données et à interagir avec elles. Ils nous permettent d’effectuer de nombreuses opérations sur vos données, telles que la sous-sélection, la transformation, la visualisation, etc.
Si vous avez effectué la configuration, vous devriez déjà avoir installé le package tidyverse. Vérifiez si vous l’avez en essayant de le charger depuis la bibliothèque :
R
## load the tidyverse packages, incl. dplyr
library("tidyverse")
Si vous avez reçu un message d’erreur
there is no package called ‘tidyverse’, c’est que vous
n’avez pas encore installé le package pour cette version de R. Pour
installer le package tidyverse, saisissez
:
R
BiocManager::install("tidyverse")
Si vous avez dû installer le package
tidyverse, n’oubliez pas de le charger
dans cette session R en utilisant la commande library()
ci-dessus !
Chargement de données avec tidyverse
Au lieu de read.csv(), nous lirons nos données à l’aide
de la fonction read_csv() (notez le _ au lieu
du .), issue du package tidyverse
readr.
R
rna <- read_csv("data/rnaseq.csv")
## view the data
rna
OUTPUT
# A tibble: 32,428 × 19
gene sample expression organism age sex infection strain time tissue
<chr> <chr> <dbl> <chr> <dbl> <chr> <chr> <chr> <dbl> <chr>
1 Asl GSM254… 1170 Mus mus… 8 Fema… Influenz… C57BL… 8 Cereb…
2 Apod GSM254… 36194 Mus mus… 8 Fema… Influenz… C57BL… 8 Cereb…
3 Cyp2d22 GSM254… 4060 Mus mus… 8 Fema… Influenz… C57BL… 8 Cereb…
4 Klk6 GSM254… 287 Mus mus… 8 Fema… Influenz… C57BL… 8 Cereb…
5 Fcrls GSM254… 85 Mus mus… 8 Fema… Influenz… C57BL… 8 Cereb…
6 Slc2a4 GSM254… 782 Mus mus… 8 Fema… Influenz… C57BL… 8 Cereb…
7 Exd2 GSM254… 1619 Mus mus… 8 Fema… Influenz… C57BL… 8 Cereb…
8 Gjc2 GSM254… 288 Mus mus… 8 Fema… Influenz… C57BL… 8 Cereb…
9 Plp1 GSM254… 43217 Mus mus… 8 Fema… Influenz… C57BL… 8 Cereb…
10 Gnb4 GSM254… 1071 Mus mus… 8 Fema… Influenz… C57BL… 8 Cereb…
# ℹ 32,418 more rows
# ℹ 9 more variables: mouse <dbl>, ENTREZID <dbl>, product <chr>,
# ensembl_gene_id <chr>, external_synonym <chr>, chromosome_name <chr>,
# gene_biotype <chr>, phenotype_description <chr>,
# hsapiens_homolog_associated_gene_name <chr>
Notez que la classe des données est désormais appelée « tibble ».
Les tibbles modifient certains comportements des objets tableau de données que nous avons présentés précédemment. La structure de données est très similaire à celle d’un tableau de données. Pour nos besoins, les seules différences sont les suivantes :
Il affiche le type de données de chaque colonne sous son nom. Notez que <
dbl> est un type de données défini pour contenir des valeurs numériques avec des décimales.Il n’affiche que les premières lignes de données et seulement autant de colonnes que celles qui tiennent sur un écran.
Nous allons maintenant découvrir certaines des fonctions
dplyr les plus courantes :
-
select(): sélectionner des colonnes -
filter(): sélectionner des lignes selon des conditions -
mutate(): créer de nouvelles colonnes en utilisant des informations provenant d’autres colonnes -
group_by()etsummarise(): créer des statistiques de synthèse sur des données regroupées -
arrange(): trier les résultats -
count(): compter les valeurs discrètes
Sélection de colonnes et filtrage de lignes
Pour sélectionner des colonnes d’un tableau de données, utilisez
select(). Le premier argument de cette fonction est le
tableau de données (rna), et les arguments suivants sont
les colonnes à conserver.
R
select(rna, gene, sample, tissue, expression)
OUTPUT
# A tibble: 32,428 × 4
gene sample tissue expression
<chr> <chr> <chr> <dbl>
1 Asl GSM2545336 Cerebellum 1170
2 Apod GSM2545336 Cerebellum 36194
3 Cyp2d22 GSM2545336 Cerebellum 4060
4 Klk6 GSM2545336 Cerebellum 287
5 Fcrls GSM2545336 Cerebellum 85
6 Slc2a4 GSM2545336 Cerebellum 782
7 Exd2 GSM2545336 Cerebellum 1619
8 Gjc2 GSM2545336 Cerebellum 288
9 Plp1 GSM2545336 Cerebellum 43217
10 Gnb4 GSM2545336 Cerebellum 1071
# ℹ 32,418 more rows
Pour sélectionner toutes les colonnes sauf certaines, placez un « - » devant la variable pour l’exclure.
R
select(rna, -tissue, -organism)
OUTPUT
# A tibble: 32,428 × 17
gene sample expression age sex infection strain time mouse ENTREZID
<chr> <chr> <dbl> <dbl> <chr> <chr> <chr> <dbl> <dbl> <dbl>
1 Asl GSM2545… 1170 8 Fema… Influenz… C57BL… 8 14 109900
2 Apod GSM2545… 36194 8 Fema… Influenz… C57BL… 8 14 11815
3 Cyp2d22 GSM2545… 4060 8 Fema… Influenz… C57BL… 8 14 56448
4 Klk6 GSM2545… 287 8 Fema… Influenz… C57BL… 8 14 19144
5 Fcrls GSM2545… 85 8 Fema… Influenz… C57BL… 8 14 80891
6 Slc2a4 GSM2545… 782 8 Fema… Influenz… C57BL… 8 14 20528
7 Exd2 GSM2545… 1619 8 Fema… Influenz… C57BL… 8 14 97827
8 Gjc2 GSM2545… 288 8 Fema… Influenz… C57BL… 8 14 118454
9 Plp1 GSM2545… 43217 8 Fema… Influenz… C57BL… 8 14 18823
10 Gnb4 GSM2545… 1071 8 Fema… Influenz… C57BL… 8 14 14696
# ℹ 32,418 more rows
# ℹ 7 more variables: product <chr>, ensembl_gene_id <chr>,
# external_synonym <chr>, chromosome_name <chr>, gene_biotype <chr>,
# phenotype_description <chr>, hsapiens_homolog_associated_gene_name <chr>
Cela sélectionnera toutes les variables de rna, à
l’exception de tissue et de organism.
Pour sélectionner des lignes en fonction d’un critère spécifique,
utilisez filter() :
R
filter(rna, sex == "Male")
OUTPUT
# A tibble: 14,740 × 19
gene sample expression organism age sex infection strain time tissue
<chr> <chr> <dbl> <chr> <dbl> <chr> <chr> <chr> <dbl> <chr>
1 Asl GSM254… 626 Mus mus… 8 Male Influenz… C57BL… 4 Cereb…
2 Apod GSM254… 13021 Mus mus… 8 Male Influenz… C57BL… 4 Cereb…
3 Cyp2d22 GSM254… 2171 Mus mus… 8 Male Influenz… C57BL… 4 Cereb…
4 Klk6 GSM254… 448 Mus mus… 8 Male Influenz… C57BL… 4 Cereb…
5 Fcrls GSM254… 180 Mus mus… 8 Male Influenz… C57BL… 4 Cereb…
6 Slc2a4 GSM254… 313 Mus mus… 8 Male Influenz… C57BL… 4 Cereb…
7 Exd2 GSM254… 2366 Mus mus… 8 Male Influenz… C57BL… 4 Cereb…
8 Gjc2 GSM254… 310 Mus mus… 8 Male Influenz… C57BL… 4 Cereb…
9 Plp1 GSM254… 53126 Mus mus… 8 Male Influenz… C57BL… 4 Cereb…
10 Gnb4 GSM254… 1355 Mus mus… 8 Male Influenz… C57BL… 4 Cereb…
# ℹ 14,730 more rows
# ℹ 9 more variables: mouse <dbl>, ENTREZID <dbl>, product <chr>,
# ensembl_gene_id <chr>, external_synonym <chr>, chromosome_name <chr>,
# gene_biotype <chr>, phenotype_description <chr>,
# hsapiens_homolog_associated_gene_name <chr>
R
filter(rna, sex == "Male" & infection == "NonInfected")
OUTPUT
# A tibble: 4,422 × 19
gene sample expression organism age sex infection strain time tissue
<chr> <chr> <dbl> <chr> <dbl> <chr> <chr> <chr> <dbl> <chr>
1 Asl GSM254… 535 Mus mus… 8 Male NonInfec… C57BL… 0 Cereb…
2 Apod GSM254… 13668 Mus mus… 8 Male NonInfec… C57BL… 0 Cereb…
3 Cyp2d22 GSM254… 2008 Mus mus… 8 Male NonInfec… C57BL… 0 Cereb…
4 Klk6 GSM254… 1101 Mus mus… 8 Male NonInfec… C57BL… 0 Cereb…
5 Fcrls GSM254… 375 Mus mus… 8 Male NonInfec… C57BL… 0 Cereb…
6 Slc2a4 GSM254… 249 Mus mus… 8 Male NonInfec… C57BL… 0 Cereb…
7 Exd2 GSM254… 3126 Mus mus… 8 Male NonInfec… C57BL… 0 Cereb…
8 Gjc2 GSM254… 791 Mus mus… 8 Male NonInfec… C57BL… 0 Cereb…
9 Plp1 GSM254… 98658 Mus mus… 8 Male NonInfec… C57BL… 0 Cereb…
10 Gnb4 GSM254… 2437 Mus mus… 8 Male NonInfec… C57BL… 0 Cereb…
# ℹ 4,412 more rows
# ℹ 9 more variables: mouse <dbl>, ENTREZID <dbl>, product <chr>,
# ensembl_gene_id <chr>, external_synonym <chr>, chromosome_name <chr>,
# gene_biotype <chr>, phenotype_description <chr>,
# hsapiens_homolog_associated_gene_name <chr>
Imaginons maintenant que nous soyons intéressés par les homologues
humains des gènes de souris analysés dans cet ensemble de données. Ces
informations se trouvent dans la dernière colonne du tibble
rna, nommée
hsapiens_homolog_associated_gene_name. Pour les visualiser
facilement, nous créerons un nouveau tableau contenant uniquement les 2
colonnes gene et
hsapiens_homolog_associated_gene_name.
R
genes <- select(rna, gene, hsapiens_homolog_associated_gene_name)
genes
OUTPUT
# A tibble: 32,428 × 2
gene hsapiens_homolog_associated_gene_name
<chr> <chr>
1 Asl ASL
2 Apod APOD
3 Cyp2d22 CYP2D6
4 Klk6 KLK6
5 Fcrls FCRL2
6 Slc2a4 SLC2A4
7 Exd2 EXD2
8 Gjc2 GJC2
9 Plp1 PLP1
10 Gnb4 GNB4
# ℹ 32,418 more rows
Certains gènes de souris n’ont pas d’homologues humains. Ceux-ci
peuvent être récupérés à l’aide de filter() et de la
fonction is.na(), qui détermine si un élément est un
NA.
R
filter(genes, is.na(hsapiens_homolog_associated_gene_name))
OUTPUT
# A tibble: 4,290 × 2
gene hsapiens_homolog_associated_gene_name
<chr> <chr>
1 Prodh <NA>
2 Tssk5 <NA>
3 Vmn2r1 <NA>
4 Gm10654 <NA>
5 Hexa <NA>
6 Sult1a1 <NA>
7 Gm6277 <NA>
8 Tmem198b <NA>
9 Adam1a <NA>
10 Ebp <NA>
# ℹ 4,280 more rows
Si nous voulons ne conserver que les gènes de souris possédant un
homologue humain, nous pouvons insérer un symbole « ! » qui nie le
résultat ; nous demandons ainsi toutes les lignes pour lesquelles
hsapiens_homolog_associated_gene_name n’est pas un
NA.
R
filter(genes, !is.na(hsapiens_homolog_associated_gene_name))
OUTPUT
# A tibble: 28,138 × 2
gene hsapiens_homolog_associated_gene_name
<chr> <chr>
1 Asl ASL
2 Apod APOD
3 Cyp2d22 CYP2D6
4 Klk6 KLK6
5 Fcrls FCRL2
6 Slc2a4 SLC2A4
7 Exd2 EXD2
8 Gjc2 GJC2
9 Plp1 PLP1
10 Gnb4 GNB4
# ℹ 28,128 more rows
Pipes
Et si vous vouliez sélectionner et filtrer simultanément ? Il existe trois façons d’y parvenir : utiliser des étapes intermédiaires, des fonctions imbriquées ou des pipes.
Avec des étapes intermédiaires, vous créez un tableau de données temporaire et vous l’utilisez comme entrée pour la fonction suivante, comme ceci :
R
rna2 <- filter(rna, sex == "Male")
rna3 <- select(rna2, gene, sample, tissue, expression)
rna3
OUTPUT
# A tibble: 14,740 × 4
gene sample tissue expression
<chr> <chr> <chr> <dbl>
1 Asl GSM2545340 Cerebellum 626
2 Apod GSM2545340 Cerebellum 13021
3 Cyp2d22 GSM2545340 Cerebellum 2171
4 Klk6 GSM2545340 Cerebellum 448
5 Fcrls GSM2545340 Cerebellum 180
6 Slc2a4 GSM2545340 Cerebellum 313
7 Exd2 GSM2545340 Cerebellum 2366
8 Gjc2 GSM2545340 Cerebellum 310
9 Plp1 GSM2545340 Cerebellum 53126
10 Gnb4 GSM2545340 Cerebellum 1355
# ℹ 14,730 more rows
C’est lisible, mais cela peut encombrer votre espace de travail avec de nombreux objets intermédiaires que vous devez nommer individuellement. Avec plusieurs étapes, cela peut s’avérer difficile à suivre.
Vous pouvez également imbriquer des fonctions (c’est-à-dire une fonction à l’intérieur d’une autre), comme ceci :
R
rna3 <- select(filter(rna, sex == "Male"), gene, sample, tissue, expression)
rna3
OUTPUT
# A tibble: 14,740 × 4
gene sample tissue expression
<chr> <chr> <chr> <dbl>
1 Asl GSM2545340 Cerebellum 626
2 Apod GSM2545340 Cerebellum 13021
3 Cyp2d22 GSM2545340 Cerebellum 2171
4 Klk6 GSM2545340 Cerebellum 448
5 Fcrls GSM2545340 Cerebellum 180
6 Slc2a4 GSM2545340 Cerebellum 313
7 Exd2 GSM2545340 Cerebellum 2366
8 Gjc2 GSM2545340 Cerebellum 310
9 Plp1 GSM2545340 Cerebellum 53126
10 Gnb4 GSM2545340 Cerebellum 1355
# ℹ 14,730 more rows
C’est pratique, mais cela peut s’avérer difficile à lire si trop de fonctions sont imbriquées, car R évalue l’expression de l’intérieur vers l’extérieur (dans ce cas, le filtrage, puis la sélection).
La dernière option, les pipes, est un ajout récent à R. Les pipes permettent de prendre la sortie d’une fonction et de la transmettre directement à la suivante, ce qui est utile lorsque l’on doit effectuer plusieurs opérations sur le même jeu de données.
Les pipes dans R ressemblent à %>% (disponible via le
package magrittr) ou à |>
(via R de base). Si vous utilisez RStudio, vous pouvez saisir le pipe
avec Ctrl + Shift + M si vous avez un
PC, ou Cmd + Shift + M si vous avez un
Mac.
Dans le code ci-dessus, nous utilisons le pipe pour envoyer d’abord
le jeu de données rna via filter() afin de
conserver les lignes où sex est Male, puis via
select() pour ne conserver que les colonnes
gene, sample, tissue et
expression.
Le pipe |> prend l’objet à sa gauche et le transmet
directement comme premier argument à la fonction à sa droite ; nous
n’avons plus besoin d’inclure explicitement le tableau de données comme
argument des fonctions filter() et
select().
R
rna |>
filter(sex == "Male") |>
select(gene, sample, tissue, expression)
OUTPUT
# A tibble: 14,740 × 4
gene sample tissue expression
<chr> <chr> <chr> <dbl>
1 Asl GSM2545340 Cerebellum 626
2 Apod GSM2545340 Cerebellum 13021
3 Cyp2d22 GSM2545340 Cerebellum 2171
4 Klk6 GSM2545340 Cerebellum 448
5 Fcrls GSM2545340 Cerebellum 180
6 Slc2a4 GSM2545340 Cerebellum 313
7 Exd2 GSM2545340 Cerebellum 2366
8 Gjc2 GSM2545340 Cerebellum 310
9 Plp1 GSM2545340 Cerebellum 53126
10 Gnb4 GSM2545340 Cerebellum 1355
# ℹ 14,730 more rows
Certains trouvent utile de lire le pipe comme le mot « puis ». Par
exemple, dans l’exemple ci-dessus, nous avons pris le tableau de données
rna, puis filtré avec filter les
lignes contenant sex == "Male", puis sélectionné
avec select les colonnes gene,
sample, tissue et expression.
Les fonctions dplyr sont en soi assez
simples, mais en les combinant dans des flux de travail linéaires à
l’aide du pipe, nous pouvons effectuer des manipulations plus complexes
de tableaux de données.
Si nous souhaitons créer un nouvel objet avec cette version réduite des données, nous pouvons lui attribuer un nouveau nom :
R
rna3 <- rna |>
filter(sex == "Male") |>
select(gene, sample, tissue, expression)
rna3
OUTPUT
# A tibble: 14,740 × 4
gene sample tissue expression
<chr> <chr> <chr> <dbl>
1 Asl GSM2545340 Cerebellum 626
2 Apod GSM2545340 Cerebellum 13021
3 Cyp2d22 GSM2545340 Cerebellum 2171
4 Klk6 GSM2545340 Cerebellum 448
5 Fcrls GSM2545340 Cerebellum 180
6 Slc2a4 GSM2545340 Cerebellum 313
7 Exd2 GSM2545340 Cerebellum 2366
8 Gjc2 GSM2545340 Cerebellum 310
9 Plp1 GSM2545340 Cerebellum 53126
10 Gnb4 GSM2545340 Cerebellum 1355
# ℹ 14,730 more rows
Défi :
À l’aide de pipes, sélectionnez les données rna pour
conserver les observations de souris femelles au temps 0, pour
lesquelles l’expression du gène est supérieure à 50000, et ne conservez
que les colonnes gene, sample,
time, expression et age.
R
rna |>
filter(expression > 50000,
sex == "Female",
time == 0 ) |>
select(gene, sample, time, expression, age)
OUTPUT
# A tibble: 9 × 5
gene sample time expression age
<chr> <chr> <dbl> <dbl> <dbl>
1 Plp1 GSM2545337 0 101241 8
2 Atp1b1 GSM2545337 0 53260 8
3 Plp1 GSM2545338 0 96534 8
4 Atp1b1 GSM2545338 0 50614 8
5 Plp1 GSM2545348 0 102790 8
6 Atp1b1 GSM2545348 0 59544 8
7 Plp1 GSM2545353 0 71237 8
8 Glul GSM2545353 0 52451 8
9 Atp1b1 GSM2545353 0 61451 8
Créer ou modifier des colonnes (mutate)
Il vous arrivera souvent de vouloir créer de nouvelles colonnes à
partir des valeurs de colonnes existantes, par exemple pour effectuer
des conversions d’unités ou pour déterminer le rapport entre des valeurs
dans deux colonnes. Pour ce faire, nous utiliserons
mutate().
Pour créer une nouvelle colonne de temps en heures :
R
rna |>
mutate(time_hours = time * 24) |>
select(time, time_hours)
OUTPUT
# A tibble: 32,428 × 2
time time_hours
<dbl> <dbl>
1 8 192
2 8 192
3 8 192
4 8 192
5 8 192
6 8 192
7 8 192
8 8 192
9 8 192
10 8 192
# ℹ 32,418 more rows
Vous pouvez également créer une deuxième nouvelle colonne en fonction
de la première nouvelle colonne au sein d’un même appel à
mutate() :
R
rna |>
mutate(time_hours = time * 24,
time_mn = time_hours * 60) |>
select(time, time_hours, time_mn)
OUTPUT
# A tibble: 32,428 × 3
time time_hours time_mn
<dbl> <dbl> <dbl>
1 8 192 11520
2 8 192 11520
3 8 192 11520
4 8 192 11520
5 8 192 11520
6 8 192 11520
7 8 192 11520
8 8 192 11520
9 8 192 11520
10 8 192 11520
# ℹ 32,418 more rows
Défi
Créez un nouveau tableau de données à partir des données
rna qui répond aux critères suivants : il ne doit contenir
que les colonnes gene, chromosome_name,
phenotype_description, sample et
expression. Les valeurs d’expression doivent être
transformées par logarithme. Ce tableau de données ne doit contenir que
des gènes situés sur les chromosomes sexuels, associés à un
phenotype_description et présentant une expression logarithmique
supérieure à 5.
Indice : réfléchissez à l’ordre des commandes pour générer ce tableau de données !
R
rna |>
mutate(expression = log(expression)) |>
select(gene, chromosome_name, phenotype_description, sample, expression) |>
filter(chromosome_name == "X" | chromosome_name == "Y") |>
filter(!is.na(phenotype_description)) |>
filter(expression > 5)
OUTPUT
# A tibble: 649 × 5
gene chromosome_name phenotype_description sample expression
<chr> <chr> <chr> <chr> <dbl>
1 Plp1 X abnormal CNS glial cell morphology GSM25… 10.7
2 Slc7a3 X decreased body length GSM25… 5.46
3 Plxnb3 X abnormal coat appearance GSM25… 6.58
4 Rbm3 X abnormal liver morphology GSM25… 9.32
5 Cfp X abnormal cardiovascular system phys… GSM25… 6.18
6 Ebp X abnormal embryonic erythrocyte morp… GSM25… 6.68
7 Cd99l2 X abnormal cellular extravasation GSM25… 8.04
8 Piga X abnormal brain development GSM25… 6.06
9 Pim2 X decreased T cell proliferation GSM25… 7.11
10 Itm2a X no abnormal phenotype detected GSM25… 7.48
# ℹ 639 more rows
Analyse de données selon le principe « séparer, appliquer, combiner »
De nombreuses tâches d’analyse de données peuvent être abordées selon
le paradigme split-apply-combine : diviser les données en
groupes, appliquer une analyse à chaque groupe, puis combiner les
résultats. dplyr rend cela très simple
grâce à l’utilisation de la fonction group_by().
R
rna |>
group_by(gene)
OUTPUT
# A tibble: 32,428 × 19
# Groups: gene [1,474]
gene sample expression organism age sex infection strain time tissue
<chr> <chr> <dbl> <chr> <dbl> <chr> <chr> <chr> <dbl> <chr>
1 Asl GSM254… 1170 Mus mus… 8 Fema… Influenz… C57BL… 8 Cereb…
2 Apod GSM254… 36194 Mus mus… 8 Fema… Influenz… C57BL… 8 Cereb…
3 Cyp2d22 GSM254… 4060 Mus mus… 8 Fema… Influenz… C57BL… 8 Cereb…
4 Klk6 GSM254… 287 Mus mus… 8 Fema… Influenz… C57BL… 8 Cereb…
5 Fcrls GSM254… 85 Mus mus… 8 Fema… Influenz… C57BL… 8 Cereb…
6 Slc2a4 GSM254… 782 Mus mus… 8 Fema… Influenz… C57BL… 8 Cereb…
7 Exd2 GSM254… 1619 Mus mus… 8 Fema… Influenz… C57BL… 8 Cereb…
8 Gjc2 GSM254… 288 Mus mus… 8 Fema… Influenz… C57BL… 8 Cereb…
9 Plp1 GSM254… 43217 Mus mus… 8 Fema… Influenz… C57BL… 8 Cereb…
10 Gnb4 GSM254… 1071 Mus mus… 8 Fema… Influenz… C57BL… 8 Cereb…
# ℹ 32,418 more rows
# ℹ 9 more variables: mouse <dbl>, ENTREZID <dbl>, product <chr>,
# ensembl_gene_id <chr>, external_synonym <chr>, chromosome_name <chr>,
# gene_biotype <chr>, phenotype_description <chr>,
# hsapiens_homolog_associated_gene_name <chr>
La fonction group_by() n’effectue aucun traitement des
données ; elle les regroupe en sous-ensembles : dans l’exemple
ci-dessus, notre tibble initial de 32428 observations est
divisé en 1474 groupes en fonction de la variable gene.
Nous pourrions également décider de regrouper le tibble selon les échantillons :
R
rna |>
group_by(sample)
OUTPUT
# A tibble: 32,428 × 19
# Groups: sample [22]
gene sample expression organism age sex infection strain time tissue
<chr> <chr> <dbl> <chr> <dbl> <chr> <chr> <chr> <dbl> <chr>
1 Asl GSM254… 1170 Mus mus… 8 Fema… Influenz… C57BL… 8 Cereb…
2 Apod GSM254… 36194 Mus mus… 8 Fema… Influenz… C57BL… 8 Cereb…
3 Cyp2d22 GSM254… 4060 Mus mus… 8 Fema… Influenz… C57BL… 8 Cereb…
4 Klk6 GSM254… 287 Mus mus… 8 Fema… Influenz… C57BL… 8 Cereb…
5 Fcrls GSM254… 85 Mus mus… 8 Fema… Influenz… C57BL… 8 Cereb…
6 Slc2a4 GSM254… 782 Mus mus… 8 Fema… Influenz… C57BL… 8 Cereb…
7 Exd2 GSM254… 1619 Mus mus… 8 Fema… Influenz… C57BL… 8 Cereb…
8 Gjc2 GSM254… 288 Mus mus… 8 Fema… Influenz… C57BL… 8 Cereb…
9 Plp1 GSM254… 43217 Mus mus… 8 Fema… Influenz… C57BL… 8 Cereb…
10 Gnb4 GSM254… 1071 Mus mus… 8 Fema… Influenz… C57BL… 8 Cereb…
# ℹ 32,418 more rows
# ℹ 9 more variables: mouse <dbl>, ENTREZID <dbl>, product <chr>,
# ensembl_gene_id <chr>, external_synonym <chr>, chromosome_name <chr>,
# gene_biotype <chr>, phenotype_description <chr>,
# hsapiens_homolog_associated_gene_name <chr>
Ici, notre ensemble initial tibble de 32428 observations
est divisé en 22 groupes en fonction de la variable
sample.
Une fois les données regroupées, les opérations suivantes s’appliqueront indépendamment à chaque groupe.
La fonction summarise()
group_by() est souvent utilisé avec
summarise(), lequel condense chaque groupe en un résumé à
une seule ligne pour ce groupe.
group_by() prend en arguments les noms de colonnes
contenant les variables catégorielles pour lesquelles
vous souhaitez calculer les statistiques de synthèse. Ainsi, pour
calculer la moyenne expression par gène :
R
rna |>
group_by(gene) |>
summarise(mean_expression = mean(expression))
OUTPUT
# A tibble: 1,474 × 2
gene mean_expression
<chr> <dbl>
1 AI504432 1053.
2 AW046200 131.
3 AW551984 295.
4 Aamp 4751.
5 Abca12 4.55
6 Abcc8 2498.
7 Abhd14a 525.
8 Abi2 4909.
9 Abi3bp 1002.
10 Abl2 2124.
# ℹ 1,464 more rows
Nous pourrions également vouloir calculer les niveaux d’expression moyens de tous les gènes dans chaque échantillon :
R
rna |>
group_by(sample) |>
summarise(mean_expression = mean(expression))
OUTPUT
# A tibble: 22 × 2
sample mean_expression
<chr> <dbl>
1 GSM2545336 2062.
2 GSM2545337 1766.
3 GSM2545338 1668.
4 GSM2545339 1696.
5 GSM2545340 1682.
6 GSM2545341 1638.
7 GSM2545342 1594.
8 GSM2545343 2107.
9 GSM2545344 1712.
10 GSM2545345 1700.
# ℹ 12 more rows
Mais nous pouvons également regrouper par plusieurs colonnes :
R
rna |>
group_by(gene, infection, time) |>
summarise(mean_expression = mean(expression))
OUTPUT
`summarise()` has regrouped the output.
ℹ Summaries were computed grouped by gene, infection, and time.
ℹ Output is grouped by gene and infection.
ℹ Use `summarise(.groups = "drop_last")` to silence this message.
ℹ Use `summarise(.by = c(gene, infection, time))` for per-operation grouping
(`?dplyr::dplyr_by`) instead.
OUTPUT
# A tibble: 4,422 × 4
# Groups: gene, infection [2,948]
gene infection time mean_expression
<chr> <chr> <dbl> <dbl>
1 AI504432 InfluenzaA 4 1104.
2 AI504432 InfluenzaA 8 1014
3 AI504432 NonInfected 0 1034.
4 AW046200 InfluenzaA 4 152.
5 AW046200 InfluenzaA 8 81
6 AW046200 NonInfected 0 155.
7 AW551984 InfluenzaA 4 302.
8 AW551984 InfluenzaA 8 342.
9 AW551984 NonInfected 0 238
10 Aamp InfluenzaA 4 4870
# ℹ 4,412 more rows
Une fois les données regroupées, vous pouvez également résumer
plusieurs variables simultanément (et pas nécessairement sur la même
variable). Par exemple, nous pourrions ajouter une colonne indiquant la
médiane de expression par gène et par condition :
R
rna |>
group_by(gene, infection, time) |>
summarise(mean_expression = mean(expression),
median_expression = median(expression))
OUTPUT
`summarise()` has regrouped the output.
ℹ Summaries were computed grouped by gene, infection, and time.
ℹ Output is grouped by gene and infection.
ℹ Use `summarise(.groups = "drop_last")` to silence this message.
ℹ Use `summarise(.by = c(gene, infection, time))` for per-operation grouping
(`?dplyr::dplyr_by`) instead.
OUTPUT
# A tibble: 4,422 × 5
# Groups: gene, infection [2,948]
gene infection time mean_expression median_expression
<chr> <chr> <dbl> <dbl> <dbl>
1 AI504432 InfluenzaA 4 1104. 1094.
2 AI504432 InfluenzaA 8 1014 985
3 AI504432 NonInfected 0 1034. 1016
4 AW046200 InfluenzaA 4 152. 144.
5 AW046200 InfluenzaA 8 81 82
6 AW046200 NonInfected 0 155. 163
7 AW551984 InfluenzaA 4 302. 245
8 AW551984 InfluenzaA 8 342. 287
9 AW551984 NonInfected 0 238 265
10 Aamp InfluenzaA 4 4870 4708
# ℹ 4,412 more rows
Défi
Calculez le niveau d’expression moyen du gène « Dok3 » par points temporels.
R
rna |>
filter(gene == "Dok3") |>
group_by(time) |>
summarise(mean = mean(expression))
OUTPUT
# A tibble: 3 × 2
time mean
<dbl> <dbl>
1 0 169
2 4 156.
3 8 61
Comptage
Lors du travail avec des données, nous souhaitons souvent connaître
le nombre d’observations pour chaque facteur ou combinaison de facteurs.
Pour cette tâche, dplyr propose
count(). Par exemple, si nous voulions compter le nombre de
lignes de données pour chaque échantillon infecté et non infecté, nous
procéderions comme suit :
R
rna |>
count(infection)
OUTPUT
# A tibble: 2 × 2
infection n
<chr> <int>
1 InfluenzaA 22110
2 NonInfected 10318
La fonction count() est une abréviation de ce que nous
avons déjà vu : regrouper par variable, puis résumer en comptant le
nombre d’observations dans ce groupe. En d’autres termes,
rna |> count(infection) équivaut à :
R
rna |>
group_by(infection) |>
summarise(n = n())
OUTPUT
# A tibble: 2 × 2
infection n
<chr> <int>
1 InfluenzaA 22110
2 NonInfected 10318
L’exemple précédent montre l’utilisation de count() pour
compter le nombre de lignes/observations pour un facteur
(c’est-à-dire infection). Si nous voulions compter une
combinaison de facteurs, telle que infection et
time, nous spécifierions le premier et le second facteur
comme arguments de count() :
R
rna |>
count(infection, time)
OUTPUT
# A tibble: 3 × 3
infection time n
<chr> <dbl> <int>
1 InfluenzaA 4 11792
2 InfluenzaA 8 10318
3 NonInfected 0 10318
ce qui équivaut à ceci :
R
rna |>
group_by(infection, time) |>
summarise(n = n())
OUTPUT
`summarise()` has regrouped the output.
ℹ Summaries were computed grouped by infection and time.
ℹ Output is grouped by infection.
ℹ Use `summarise(.groups = "drop_last")` to silence this message.
ℹ Use `summarise(.by = c(infection, time))` for per-operation grouping
(`?dplyr::dplyr_by`) instead.
OUTPUT
# A tibble: 3 × 3
# Groups: infection [2]
infection time n
<chr> <dbl> <int>
1 InfluenzaA 4 11792
2 InfluenzaA 8 10318
3 NonInfected 0 10318
Il est parfois utile de trier le résultat pour faciliter les
comparaisons. Nous pouvons utiliser arrange() pour trier le
tableau. Par exemple, nous pourrions vouloir classer le tableau
ci-dessus par temps :
R
rna |>
count(infection, time) |>
arrange(time)
OUTPUT
# A tibble: 3 × 3
infection time n
<chr> <dbl> <int>
1 NonInfected 0 10318
2 InfluenzaA 4 11792
3 InfluenzaA 8 10318
ou par nombres :
R
rna |>
count(infection, time) |>
arrange(n)
OUTPUT
# A tibble: 3 × 3
infection time n
<chr> <dbl> <int>
1 InfluenzaA 8 10318
2 NonInfected 0 10318
3 InfluenzaA 4 11792
Pour trier par ordre décroissant, nous devons ajouter la fonction
desc() :
R
rna |>
count(infection, time) |>
arrange(desc(n))
OUTPUT
# A tibble: 3 × 3
infection time n
<chr> <dbl> <int>
1 InfluenzaA 4 11792
2 InfluenzaA 8 10318
3 NonInfected 0 10318
Défi
- Combien de gènes ont été analysés dans chaque échantillon ?
- Utilisez
group_by()etsummarise()pour évaluer la profondeur de séquençage (la somme de tous les comptages) dans chaque échantillon. Quel échantillon présente la profondeur de séquençage la plus élevée ? - Choisissez un échantillon et évaluez le nombre de gènes par biotype.
- Identifiez les gènes associés à la description du phénotype « abnormal DNA methylation », et calculez leur expression moyenne (en log) aux moments 0, 4 et 8.
R
## 1.
rna |>
count(sample)
OUTPUT
# A tibble: 22 × 2
sample n
<chr> <int>
1 GSM2545336 1474
2 GSM2545337 1474
3 GSM2545338 1474
4 GSM2545339 1474
5 GSM2545340 1474
6 GSM2545341 1474
7 GSM2545342 1474
8 GSM2545343 1474
9 GSM2545344 1474
10 GSM2545345 1474
# ℹ 12 more rows
R
## 2.
rna |>
group_by(sample) |>
summarise(seq_depth = sum(expression)) |>
arrange(desc(seq_depth))
OUTPUT
# A tibble: 22 × 2
sample seq_depth
<chr> <dbl>
1 GSM2545350 3255566
2 GSM2545352 3216163
3 GSM2545343 3105652
4 GSM2545336 3039671
5 GSM2545380 3036098
6 GSM2545353 2953249
7 GSM2545348 2913678
8 GSM2545362 2913517
9 GSM2545351 2782464
10 GSM2545349 2758006
# ℹ 12 more rows
R
## 3.
rna |>
filter(sample == "GSM2545336") |>
count(gene_biotype) |>
arrange(desc(n))
OUTPUT
# A tibble: 13 × 2
gene_biotype n
<chr> <int>
1 protein_coding 1321
2 lncRNA 69
3 processed_pseudogene 59
4 miRNA 7
5 snoRNA 5
6 TEC 4
7 polymorphic_pseudogene 2
8 unprocessed_pseudogene 2
9 IG_C_gene 1
10 scaRNA 1
11 transcribed_processed_pseudogene 1
12 transcribed_unitary_pseudogene 1
13 transcribed_unprocessed_pseudogene 1
R
## 4.
rna |>
filter(phenotype_description == "abnormal DNA methylation") |>
group_by(gene, time) |>
summarise(mean_expression = mean(log(expression))) |>
arrange()
OUTPUT
`summarise()` has regrouped the output.
ℹ Summaries were computed grouped by gene and time.
ℹ Output is grouped by gene.
ℹ Use `summarise(.groups = "drop_last")` to silence this message.
ℹ Use `summarise(.by = c(gene, time))` for per-operation grouping
(`?dplyr::dplyr_by`) instead.
OUTPUT
# A tibble: 6 × 3
# Groups: gene [2]
gene time mean_expression
<chr> <dbl> <dbl>
1 Xist 0 6.95
2 Xist 4 6.34
3 Xist 8 7.13
4 Zdbf2 0 6.27
5 Zdbf2 4 6.27
6 Zdbf2 8 6.19
Restructuration des données
Dans le tableau rna, les lignes contiennent des valeurs
d’expression (l’unité) associées à une combinaison de 2 autres variables
: gene et sample.
Toutes les autres colonnes correspondent à des variables décrivant soit l’échantillon (organisme, âge, sexe, …), soit le gène (gene_biotype, ENTREZ_ID, product, …). Les variables qui ne varient pas selon les gènes ou les échantillons auront la même valeur dans toutes les lignes.
R
rna |>
arrange(gene)
OUTPUT
# A tibble: 32,428 × 19
gene sample expression organism age sex infection strain time tissue
<chr> <chr> <dbl> <chr> <dbl> <chr> <chr> <chr> <dbl> <chr>
1 AI504432 GSM25… 1230 Mus mus… 8 Fema… Influenz… C57BL… 8 Cereb…
2 AI504432 GSM25… 1085 Mus mus… 8 Fema… NonInfec… C57BL… 0 Cereb…
3 AI504432 GSM25… 969 Mus mus… 8 Fema… NonInfec… C57BL… 0 Cereb…
4 AI504432 GSM25… 1284 Mus mus… 8 Fema… Influenz… C57BL… 4 Cereb…
5 AI504432 GSM25… 966 Mus mus… 8 Male Influenz… C57BL… 4 Cereb…
6 AI504432 GSM25… 918 Mus mus… 8 Male Influenz… C57BL… 8 Cereb…
7 AI504432 GSM25… 985 Mus mus… 8 Fema… Influenz… C57BL… 8 Cereb…
8 AI504432 GSM25… 972 Mus mus… 8 Male NonInfec… C57BL… 0 Cereb…
9 AI504432 GSM25… 1000 Mus mus… 8 Fema… Influenz… C57BL… 4 Cereb…
10 AI504432 GSM25… 816 Mus mus… 8 Male Influenz… C57BL… 4 Cereb…
# ℹ 32,418 more rows
# ℹ 9 more variables: mouse <dbl>, ENTREZID <dbl>, product <chr>,
# ensembl_gene_id <chr>, external_synonym <chr>, chromosome_name <chr>,
# gene_biotype <chr>, phenotype_description <chr>,
# hsapiens_homolog_associated_gene_name <chr>
Cette structure est appelée long-format, car une seule
colonne contient toutes les valeurs, et une ou plusieurs autres colonnes
décrivent le contexte de chaque valeur.
Dans certains cas, le long-format n’est pas vraiment «
lisible par l’humain », et un autre format, le wide-format,
est préféré, car il permet de représenter les données de manière plus
compacte. C’est généralement le cas pour les valeurs d’expression
génique, que les scientifiques ont l’habitude de consulter sous forme de
matrices, où les lignes représentent les gènes et les colonnes les
échantillons.
Dans ce format, il deviendrait donc simple d’explorer la relation entre les niveaux d’expression génique au sein des échantillons, ainsi qu’entre eux.
OUTPUT
# A tibble: 1,474 × 23
gene GSM2545336 GSM2545337 GSM2545338 GSM2545339 GSM2545340 GSM2545341
<chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
1 Asl 1170 361 400 586 626 988
2 Apod 36194 10347 9173 10620 13021 29594
3 Cyp2d22 4060 1616 1603 1901 2171 3349
4 Klk6 287 629 641 578 448 195
5 Fcrls 85 233 244 237 180 38
6 Slc2a4 782 231 248 265 313 786
7 Exd2 1619 2288 2235 2513 2366 1359
8 Gjc2 288 595 568 551 310 146
9 Plp1 43217 101241 96534 58354 53126 27173
10 Gnb4 1071 1791 1867 1430 1355 798
# ℹ 1,464 more rows
# ℹ 16 more variables: GSM2545342 <dbl>, GSM2545343 <dbl>, GSM2545344 <dbl>,
# GSM2545345 <dbl>, GSM2545346 <dbl>, GSM2545347 <dbl>, GSM2545348 <dbl>,
# GSM2545349 <dbl>, GSM2545350 <dbl>, GSM2545351 <dbl>, GSM2545352 <dbl>,
# GSM2545353 <dbl>, GSM2545354 <dbl>, GSM2545362 <dbl>, GSM2545363 <dbl>,
# GSM2545380 <dbl>
Pour convertir les valeurs d’expression génique de rna
en format large, nous devons créer un nouveau tableau où les valeurs de
la colonne sample deviendraient les noms des variables de
colonne.
Le point clé ici est que nous suivons toujours une structure de données ordonnée, mais que nous avons reformaté les données en fonction des observations d’intérêt : les niveaux d’expression par gène, au lieu de les enregistrer par gène et par échantillon.
La transformation inverse consisterait à transformer les noms de colonnes en valeurs d’une nouvelle variable.
Nous pouvons effectuer ces deux transformations à l’aide de deux
fonctions tidyr, pivot_longer() et
pivot_wider() (voir l’article sur les pivots sur le
site web de tidyr pour plus de détails).
Conversion des données vers un format plus large
Sélectionnons les 3 premières colonnes de rna et
utilisons pivot_wider() pour transformer les données en
format large.
R
rna_exp <- rna |>
select(gene, sample, expression)
rna_exp
OUTPUT
# A tibble: 32,428 × 3
gene sample expression
<chr> <chr> <dbl>
1 Asl GSM2545336 1170
2 Apod GSM2545336 36194
3 Cyp2d22 GSM2545336 4060
4 Klk6 GSM2545336 287
5 Fcrls GSM2545336 85
6 Slc2a4 GSM2545336 782
7 Exd2 GSM2545336 1619
8 Gjc2 GSM2545336 288
9 Plp1 GSM2545336 43217
10 Gnb4 GSM2545336 1071
# ℹ 32,418 more rows
pivot_wider prend trois arguments principaux :
- les données à transformer ;
- le
names_from: la colonne dont les valeurs deviendront de nouveaux noms de colonnes ; - le
values_from: la colonne dont les valeurs rempliront les nouvelles colonnes.

rna data.
R
rna_wide <- rna_exp |>
pivot_wider(names_from = sample,
values_from = expression)
rna_wide
OUTPUT
# A tibble: 1,474 × 23
gene GSM2545336 GSM2545337 GSM2545338 GSM2545339 GSM2545340 GSM2545341
<chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
1 Asl 1170 361 400 586 626 988
2 Apod 36194 10347 9173 10620 13021 29594
3 Cyp2d22 4060 1616 1603 1901 2171 3349
4 Klk6 287 629 641 578 448 195
5 Fcrls 85 233 244 237 180 38
6 Slc2a4 782 231 248 265 313 786
7 Exd2 1619 2288 2235 2513 2366 1359
8 Gjc2 288 595 568 551 310 146
9 Plp1 43217 101241 96534 58354 53126 27173
10 Gnb4 1071 1791 1867 1430 1355 798
# ℹ 1,464 more rows
# ℹ 16 more variables: GSM2545342 <dbl>, GSM2545343 <dbl>, GSM2545344 <dbl>,
# GSM2545345 <dbl>, GSM2545346 <dbl>, GSM2545347 <dbl>, GSM2545348 <dbl>,
# GSM2545349 <dbl>, GSM2545350 <dbl>, GSM2545351 <dbl>, GSM2545352 <dbl>,
# GSM2545353 <dbl>, GSM2545354 <dbl>, GSM2545362 <dbl>, GSM2545363 <dbl>,
# GSM2545380 <dbl>
Notez que, par défaut, la fonction pivot_wider()
ajoutera NA pour les valeurs manquantes.
Imaginons que, pour une raison quelconque, nous ayons des valeurs d’expression manquantes pour certains gènes dans certains échantillons. Dans l’exemple fictif suivant, le gène Cyp2d22 ne possède qu’une seule valeur d’expression, dans l’échantillon GSM2545338.
R
rna_with_missing_values <- rna |>
select(gene, sample, expression) |>
filter(gene %in% c("Asl", "Apod", "Cyp2d22")) |>
filter(sample %in% c("GSM2545336", "GSM2545337", "GSM2545338")) |>
arrange(sample) |>
filter(!(gene == "Cyp2d22" & sample != "GSM2545338"))
rna_with_missing_values
OUTPUT
# A tibble: 7 × 3
gene sample expression
<chr> <chr> <dbl>
1 Asl GSM2545336 1170
2 Apod GSM2545336 36194
3 Asl GSM2545337 361
4 Apod GSM2545337 10347
5 Asl GSM2545338 400
6 Apod GSM2545338 9173
7 Cyp2d22 GSM2545338 1603
Par défaut, la fonction pivot_wider() ajoute
NA pour les valeurs manquantes. Cela peut être paramétré
via l’argument values_fill de la fonction
pivot_wider().
R
rna_with_missing_values |>
pivot_wider(names_from = sample,
values_from = expression)
OUTPUT
# A tibble: 3 × 4
gene GSM2545336 GSM2545337 GSM2545338
<chr> <dbl> <dbl> <dbl>
1 Asl 1170 361 400
2 Apod 36194 10347 9173
3 Cyp2d22 NA NA 1603
R
rna_with_missing_values |>
pivot_wider(names_from = sample,
values_from = expression,
values_fill = 0)
OUTPUT
# A tibble: 3 × 4
gene GSM2545336 GSM2545337 GSM2545338
<chr> <dbl> <dbl> <dbl>
1 Asl 1170 361 400
2 Apod 36194 10347 9173
3 Cyp2d22 0 0 1603
Conversion des données vers un format plus long
Dans le cas inverse, nous utilisons les noms de colonnes pour les transformer en une paire de nouvelles variables. L’une des variables représente les noms de colonnes sous forme de valeurs, et l’autre contient les valeurs précédemment associées aux noms de colonnes.
pivot_longer() prend quatre arguments principaux :
- les données à transformer ;
- le
names_to: le nouveau nom de colonne que nous souhaitons créer et remplir avec les noms actuels des colonnes ; - le
values_to: le nouveau nom de colonne que nous souhaitons créer et remplir avec les valeurs actuelles ; - les noms des colonnes à utiliser pour remplir les variables
names_toetvalues_to(ou à supprimer).

rna data.
Pour recréer rna_long à partir de rna_wide,
nous créerions une clé appelée sample et une valeur appelée
expression, et utiliserions toutes les colonnes sauf
gene pour la variable clé. Ici, nous supprimons la colonne
gene avec un signe moins.
Notez comment les nouveaux noms de variables doivent être entourés de guillemets ici.
R
rna_long <- rna_wide |>
pivot_longer(names_to = "sample",
values_to = "expression",
-gene)
rna_long
OUTPUT
# A tibble: 32,428 × 3
gene sample expression
<chr> <chr> <dbl>
1 Asl GSM2545336 1170
2 Asl GSM2545337 361
3 Asl GSM2545338 400
4 Asl GSM2545339 586
5 Asl GSM2545340 626
6 Asl GSM2545341 988
7 Asl GSM2545342 836
8 Asl GSM2545343 535
9 Asl GSM2545344 586
10 Asl GSM2545345 597
# ℹ 32,418 more rows
Nous aurions également pu utiliser une spécification pour déterminer
les colonnes à inclure. Cela peut s’avérer utile si vous disposez d’un
grand nombre de colonnes d’identification, et il est plus simple de
spécifier ce qu’il faut récupérer que ce qu’il faut laisser de côté.
Ici, la fonction starts_with() peut aider à récupérer les
noms d’échantillons sans avoir à tous les énumérer ! Une autre
possibilité serait d’utiliser l’opérateur : !
R
rna_wide |>
pivot_longer(names_to = "sample",
values_to = "expression",
cols = starts_with("GSM"))
OUTPUT
# A tibble: 32,428 × 3
gene sample expression
<chr> <chr> <dbl>
1 Asl GSM2545336 1170
2 Asl GSM2545337 361
3 Asl GSM2545338 400
4 Asl GSM2545339 586
5 Asl GSM2545340 626
6 Asl GSM2545341 988
7 Asl GSM2545342 836
8 Asl GSM2545343 535
9 Asl GSM2545344 586
10 Asl GSM2545345 597
# ℹ 32,418 more rows
R
rna_wide |>
pivot_longer(names_to = "sample",
values_to = "expression",
GSM2545336:GSM2545380)
OUTPUT
# A tibble: 32,428 × 3
gene sample expression
<chr> <chr> <dbl>
1 Asl GSM2545336 1170
2 Asl GSM2545337 361
3 Asl GSM2545338 400
4 Asl GSM2545339 586
5 Asl GSM2545340 626
6 Asl GSM2545341 988
7 Asl GSM2545342 836
8 Asl GSM2545343 535
9 Asl GSM2545344 586
10 Asl GSM2545345 597
# ℹ 32,418 more rows
Notez que si nous avions des valeurs manquantes dans le format large,
le NA serait inclus dans le nouveau format long.
Rappelons notre tibble fictif précédent contenant des valeurs manquantes :
R
rna_with_missing_values
OUTPUT
# A tibble: 7 × 3
gene sample expression
<chr> <chr> <dbl>
1 Asl GSM2545336 1170
2 Apod GSM2545336 36194
3 Asl GSM2545337 361
4 Apod GSM2545337 10347
5 Asl GSM2545338 400
6 Apod GSM2545338 9173
7 Cyp2d22 GSM2545338 1603
R
wide_with_NA <- rna_with_missing_values |>
pivot_wider(names_from = sample,
values_from = expression)
wide_with_NA
OUTPUT
# A tibble: 3 × 4
gene GSM2545336 GSM2545337 GSM2545338
<chr> <dbl> <dbl> <dbl>
1 Asl 1170 361 400
2 Apod 36194 10347 9173
3 Cyp2d22 NA NA 1603
R
wide_with_NA |>
pivot_longer(names_to = "sample",
values_to = "expression",
-gene)
OUTPUT
# A tibble: 9 × 3
gene sample expression
<chr> <chr> <dbl>
1 Asl GSM2545336 1170
2 Asl GSM2545337 361
3 Asl GSM2545338 400
4 Apod GSM2545336 36194
5 Apod GSM2545337 10347
6 Apod GSM2545338 9173
7 Cyp2d22 GSM2545336 NA
8 Cyp2d22 GSM2545337 NA
9 Cyp2d22 GSM2545338 1603
Le passage aux formats large et long peut être un moyen utile d’équilibrer un jeu de données afin que chaque réplicat ait la même composition.
Question
À partir du tableau rna, utilisez la fonction
pivot_wider() pour créer un tableau au format large
présentant les niveaux d’expression génique dans chaque souris. Ensuite,
utilisez la fonction pivot_longer() pour restaurer un
tableau au format long.
R
rna1 <- rna |>
select(gene, mouse, expression) |>
pivot_wider(names_from = mouse, values_from = expression)
rna1
OUTPUT
# A tibble: 1,474 × 23
gene `14` `9` `10` `15` `18` `6` `5` `11` `22` `13` `23`
<chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
1 Asl 1170 361 400 586 626 988 836 535 586 597 938
2 Apod 36194 10347 9173 10620 13021 29594 24959 13668 13230 15868 27769
3 Cyp2d22 4060 1616 1603 1901 2171 3349 3122 2008 2254 2277 2985
4 Klk6 287 629 641 578 448 195 186 1101 537 567 327
5 Fcrls 85 233 244 237 180 38 68 375 199 177 89
6 Slc2a4 782 231 248 265 313 786 528 249 266 357 654
7 Exd2 1619 2288 2235 2513 2366 1359 1474 3126 2379 2173 1531
8 Gjc2 288 595 568 551 310 146 186 791 454 370 240
9 Plp1 43217 101241 96534 58354 53126 27173 28728 98658 61356 61647 38019
10 Gnb4 1071 1791 1867 1430 1355 798 806 2437 1394 1554 960
# ℹ 1,464 more rows
# ℹ 11 more variables: `24` <dbl>, `8` <dbl>, `7` <dbl>, `1` <dbl>, `16` <dbl>,
# `21` <dbl>, `4` <dbl>, `2` <dbl>, `20` <dbl>, `12` <dbl>, `19` <dbl>
R
rna1 |>
pivot_longer(names_to = "mouse_id", values_to = "counts", -gene)
OUTPUT
# A tibble: 32,428 × 3
gene mouse_id counts
<chr> <chr> <dbl>
1 Asl 14 1170
2 Asl 9 361
3 Asl 10 400
4 Asl 15 586
5 Asl 18 626
6 Asl 6 988
7 Asl 5 836
8 Asl 11 535
9 Asl 22 586
10 Asl 13 597
# ℹ 32,418 more rows
Question
Extrayez les gènes situés sur les chromosomes X et Y du tableau de
données rna et étalez le tableau de données avec
sex comme colonnes, chromosome_name comme
lignes, et la moyenne de l’expression des gènes situés sur chaque
chromosome comme valeurs, comme dans le tibble suivant :

Vous devrez effectuer un résumé avant de restructurer !
Calculons d’abord le niveau d’expression moyen des gènes liés aux chromosomes X et Y dans les échantillons provenant de souris mâles et femelles…
R
rna |>
filter(chromosome_name == "Y" | chromosome_name == "X") |>
group_by(sex, chromosome_name) |>
summarise(mean = mean(expression))
OUTPUT
`summarise()` has regrouped the output.
ℹ Summaries were computed grouped by sex and chromosome_name.
ℹ Output is grouped by sex.
ℹ Use `summarise(.groups = "drop_last")` to silence this message.
ℹ Use `summarise(.by = c(sex, chromosome_name))` for per-operation grouping
(`?dplyr::dplyr_by`) instead.
OUTPUT
# A tibble: 4 × 3
# Groups: sex [2]
sex chromosome_name mean
<chr> <chr> <dbl>
1 Female X 3504.
2 Female Y 3
3 Male X 2497.
4 Male Y 2117.
Et pivoter la table au format large
R
rna_1 <- rna |>
filter(chromosome_name == "Y" | chromosome_name == "X") |>
group_by(sex, chromosome_name) |>
summarise(mean = mean(expression)) |>
pivot_wider(names_from = sex,
values_from = mean)
OUTPUT
`summarise()` has regrouped the output.
ℹ Summaries were computed grouped by sex and chromosome_name.
ℹ Output is grouped by sex.
ℹ Use `summarise(.groups = "drop_last")` to silence this message.
ℹ Use `summarise(.by = c(sex, chromosome_name))` for per-operation grouping
(`?dplyr::dplyr_by`) instead.
R
rna_1
OUTPUT
# A tibble: 2 × 3
chromosome_name Female Male
<chr> <dbl> <dbl>
1 X 3504. 2497.
2 Y 3 2117.
Prenez maintenant ce tableau de données et transformez-le avec
pivot_longer() afin que chaque ligne représente une
combinaison unique chromosome_name par
gender.
R
rna_1 |>
pivot_longer(names_to = "gender",
values_to = "mean",
-chromosome_name)
OUTPUT
# A tibble: 4 × 3
chromosome_name gender mean
<chr> <chr> <dbl>
1 X Female 3504.
2 X Male 2497.
3 Y Female 3
4 Y Male 2117.
Question
Utilisez le jeu de données rna pour créer une matrice
d’expression où chaque ligne représente les niveaux d’expression moyens
des gènes et chaque colonne représente les différents moments
temporels.
Calculons d’abord l’expression moyenne par gène et par moment
R
rna |>
group_by(gene, time) |>
summarise(mean_exp = mean(expression))
OUTPUT
`summarise()` has regrouped the output.
ℹ Summaries were computed grouped by gene and time.
ℹ Output is grouped by gene.
ℹ Use `summarise(.groups = "drop_last")` to silence this message.
ℹ Use `summarise(.by = c(gene, time))` for per-operation grouping
(`?dplyr::dplyr_by`) instead.
OUTPUT
# A tibble: 4,422 × 3
# Groups: gene [1,474]
gene time mean_exp
<chr> <dbl> <dbl>
1 AI504432 0 1034.
2 AI504432 4 1104.
3 AI504432 8 1014
4 AW046200 0 155.
5 AW046200 4 152.
6 AW046200 8 81
7 AW551984 0 238
8 AW551984 4 302.
9 AW551984 8 342.
10 Aamp 0 4603.
# ℹ 4,412 more rows
avant d’utiliser la fonction pivot_wider()
R
rna_time <- rna |>
group_by(gene, time) |>
summarise(mean_exp = mean(expression)) |>
pivot_wider(names_from = time,
values_from = mean_exp)
OUTPUT
`summarise()` has regrouped the output.
ℹ Summaries were computed grouped by gene and time.
ℹ Output is grouped by gene.
ℹ Use `summarise(.groups = "drop_last")` to silence this message.
ℹ Use `summarise(.by = c(gene, time))` for per-operation grouping
(`?dplyr::dplyr_by`) instead.
R
rna_time
OUTPUT
# A tibble: 1,474 × 4
# Groups: gene [1,474]
gene `0` `4` `8`
<chr> <dbl> <dbl> <dbl>
1 AI504432 1034. 1104. 1014
2 AW046200 155. 152. 81
3 AW551984 238 302. 342.
4 Aamp 4603. 4870 4763.
5 Abca12 5.29 4.25 4.14
6 Abcc8 2576. 2609. 2292.
7 Abhd14a 591. 547. 432.
8 Abi2 4881. 4903. 4945.
9 Abi3bp 1175. 1061. 762.
10 Abl2 2170. 2078. 2131.
# ℹ 1,464 more rows
Notez que cela génère un tibble dont certains noms de colonnes commencent par un chiffre. Si nous voulions sélectionner la colonne correspondant aux temps, nous ne pourrions pas utiliser les noms de colonnes directement… Que se passe-t-il lorsque nous sélectionnons la colonne 4 ?
R
rna |>
group_by(gene, time) |>
summarise(mean_exp = mean(expression)) |>
pivot_wider(names_from = time,
values_from = mean_exp) |>
select(gene, 4)
OUTPUT
`summarise()` has regrouped the output.
ℹ Summaries were computed grouped by gene and time.
ℹ Output is grouped by gene.
ℹ Use `summarise(.groups = "drop_last")` to silence this message.
ℹ Use `summarise(.by = c(gene, time))` for per-operation grouping
(`?dplyr::dplyr_by`) instead.
OUTPUT
# A tibble: 1,474 × 2
# Groups: gene [1,474]
gene `8`
<chr> <dbl>
1 AI504432 1014
2 AW046200 81
3 AW551984 342.
4 Aamp 4763.
5 Abca12 4.14
6 Abcc8 2292.
7 Abhd14a 432.
8 Abi2 4945.
9 Abi3bp 762.
10 Abl2 2131.
# ℹ 1,464 more rows
Pour sélectionner le temps 4, nous devrions entourer le nom de la colonne d’accents graves « ` ».
R
rna |>
group_by(gene, time) |>
summarise(mean_exp = mean(expression)) |>
pivot_wider(names_from = time,
values_from = mean_exp) |>
select(gene, `4`)
OUTPUT
`summarise()` has regrouped the output.
ℹ Summaries were computed grouped by gene and time.
ℹ Output is grouped by gene.
ℹ Use `summarise(.groups = "drop_last")` to silence this message.
ℹ Use `summarise(.by = c(gene, time))` for per-operation grouping
(`?dplyr::dplyr_by`) instead.
OUTPUT
# A tibble: 1,474 × 2
# Groups: gene [1,474]
gene `4`
<chr> <dbl>
1 AI504432 1104.
2 AW046200 152.
3 AW551984 302.
4 Aamp 4870
5 Abca12 4.25
6 Abcc8 2609.
7 Abhd14a 547.
8 Abi2 4903.
9 Abi3bp 1061.
10 Abl2 2078.
# ℹ 1,464 more rows
Une autre possibilité consisterait à renommer la colonne, en choisissant un nom qui ne commence pas par un chiffre :
R
rna |>
group_by(gene, time) |>
summarise(mean_exp = mean(expression)) |>
pivot_wider(names_from = time,
values_from = mean_exp) |>
rename("time0" = `0`, "time4" = `4`, "time8" = `8`) |>
select(gene, time4)
OUTPUT
`summarise()` has regrouped the output.
ℹ Summaries were computed grouped by gene and time.
ℹ Output is grouped by gene.
ℹ Use `summarise(.groups = "drop_last")` to silence this message.
ℹ Use `summarise(.by = c(gene, time))` for per-operation grouping
(`?dplyr::dplyr_by`) instead.
OUTPUT
# A tibble: 1,474 × 2
# Groups: gene [1,474]
gene time4
<chr> <dbl>
1 AI504432 1104.
2 AW046200 152.
3 AW551984 302.
4 Aamp 4870
5 Abca12 4.25
6 Abcc8 2609.
7 Abhd14a 547.
8 Abi2 4903.
9 Abi3bp 1061.
10 Abl2 2078.
# ℹ 1,464 more rows
Question
Utilisez le tableau de données précédent contenant les niveaux d’expression moyens par temps et créez une nouvelle colonne contenant les rapports d’expression (fold changes) entre le temps 8 et le temps 0, ainsi qu’entre le temps 8 et le temps 4. Convertissez ce tableau au format long en rassemblant les rapports d’expression calculés.
À partir du tibble rna_time :
R
rna_time
OUTPUT
# A tibble: 1,474 × 4
# Groups: gene [1,474]
gene `0` `4` `8`
<chr> <dbl> <dbl> <dbl>
1 AI504432 1034. 1104. 1014
2 AW046200 155. 152. 81
3 AW551984 238 302. 342.
4 Aamp 4603. 4870 4763.
5 Abca12 5.29 4.25 4.14
6 Abcc8 2576. 2609. 2292.
7 Abhd14a 591. 547. 432.
8 Abi2 4881. 4903. 4945.
9 Abi3bp 1175. 1061. 762.
10 Abl2 2170. 2078. 2131.
# ℹ 1,464 more rows
Calculez les rapports d’expression (fold changes) :
R
rna_time |>
mutate(time_8_vs_0 = `8` / `0`, time_8_vs_4 = `8` / `4`)
OUTPUT
# A tibble: 1,474 × 6
# Groups: gene [1,474]
gene `0` `4` `8` time_8_vs_0 time_8_vs_4
<chr> <dbl> <dbl> <dbl> <dbl> <dbl>
1 AI504432 1034. 1104. 1014 0.981 0.918
2 AW046200 155. 152. 81 0.522 0.532
3 AW551984 238 302. 342. 1.44 1.13
4 Aamp 4603. 4870 4763. 1.03 0.978
5 Abca12 5.29 4.25 4.14 0.784 0.975
6 Abcc8 2576. 2609. 2292. 0.889 0.878
7 Abhd14a 591. 547. 432. 0.731 0.791
8 Abi2 4881. 4903. 4945. 1.01 1.01
9 Abi3bp 1175. 1061. 762. 0.649 0.719
10 Abl2 2170. 2078. 2131. 0.982 1.03
# ℹ 1,464 more rows
Et utilisez la fonction pivot_longer() :
R
rna_time |>
mutate(time_8_vs_0 = `8` / `0`, time_8_vs_4 = `8` / `4`) |>
pivot_longer(names_to = "comparisons",
values_to = "Fold_changes",
time_8_vs_0:time_8_vs_4)
OUTPUT
# A tibble: 2,948 × 6
# Groups: gene [1,474]
gene `0` `4` `8` comparisons Fold_changes
<chr> <dbl> <dbl> <dbl> <chr> <dbl>
1 AI504432 1034. 1104. 1014 time_8_vs_0 0.981
2 AI504432 1034. 1104. 1014 time_8_vs_4 0.918
3 AW046200 155. 152. 81 time_8_vs_0 0.522
4 AW046200 155. 152. 81 time_8_vs_4 0.532
5 AW551984 238 302. 342. time_8_vs_0 1.44
6 AW551984 238 302. 342. time_8_vs_4 1.13
7 Aamp 4603. 4870 4763. time_8_vs_0 1.03
8 Aamp 4603. 4870 4763. time_8_vs_4 0.978
9 Abca12 5.29 4.25 4.14 time_8_vs_0 0.784
10 Abca12 5.29 4.25 4.14 time_8_vs_4 0.975
# ℹ 2,938 more rows
Jointure de tableaux
Dans de nombreuses situations concrètes, les données sont réparties sur plusieurs tables. Cela se produit généralement parce que différents types d’informations sont recueillis à partir de sources distinctes.
Pour certaines analyses, il peut être souhaitable de combiner les données de deux tables ou plus dans un seul tableau de données, en s’appuyant sur une colonne commune à toutes les tables.
Le package dplyr propose un ensemble de fonctions de
jointure permettant de combiner deux tableaux de données en fonction de
correspondances dans des colonnes spécifiées. Nous présentons ici une
brève introduction aux jointures. Pour en savoir plus, veuillez vous
référer au chapitre sur les jointures
de tableaux. La fiche
pratique sur la transformation des données propose également un bref
aperçu des jointures de tableaux.
Nous allons illustrer la jointure à l’aide d’un petit tableau,
rna_mini, que nous créerons en extrayant un sous-ensemble
du tableau d’origine rna, en ne gardant que 3 colonnes et
10 lignes.
R
rna_mini <- rna |>
select(gene, sample, expression) |>
head(10)
rna_mini
OUTPUT
# A tibble: 10 × 3
gene sample expression
<chr> <chr> <dbl>
1 Asl GSM2545336 1170
2 Apod GSM2545336 36194
3 Cyp2d22 GSM2545336 4060
4 Klk6 GSM2545336 287
5 Fcrls GSM2545336 85
6 Slc2a4 GSM2545336 782
7 Exd2 GSM2545336 1619
8 Gjc2 GSM2545336 288
9 Plp1 GSM2545336 43217
10 Gnb4 GSM2545336 1071
La deuxième table, annot1, contient 2 colonnes, gene et
gene_description. Vous pouvez soit télécharger
annot1.csv en cliquant sur le lien puis en le déplaçant dans le
dossier data/, soit utiliser le code R ci-dessous pour le
télécharger directement dans le dossier.
R
download.file(url = "https://carpentries-incubator.github.io/bioc-intro/data/annot1.csv",
destfile = "data/annot1.csv")
annot1 <- read_csv(file = "data/annot1.csv")
annot1
OUTPUT
# A tibble: 10 × 2
gene gene_description
<chr> <chr>
1 Cyp2d22 cytochrome P450, family 2, subfamily d, polypeptide 22 [Source:MGI S…
2 Klk6 kallikrein related-peptidase 6 [Source:MGI Symbol;Acc:MGI:1343166]
3 Fcrls Fc receptor-like S, scavenger receptor [Source:MGI Symbol;Acc:MGI:19…
4 Plp1 proteolipid protein (myelin) 1 [Source:MGI Symbol;Acc:MGI:97623]
5 Exd2 exonuclease 3'-5' domain containing 2 [Source:MGI Symbol;Acc:MGI:192…
6 Apod apolipoprotein D [Source:MGI Symbol;Acc:MGI:88056]
7 Gnb4 guanine nucleotide binding protein (G protein), beta 4 [Source:MGI S…
8 Slc2a4 solute carrier family 2 (facilitated glucose transporter), member 4 …
9 Asl argininosuccinate lyase [Source:MGI Symbol;Acc:MGI:88084]
10 Gjc2 gap junction protein, gamma 2 [Source:MGI Symbol;Acc:MGI:2153060]
Nous souhaitons maintenant joindre ces deux tables en une seule
contenant toutes les variables à l’aide de la fonction
full_join() du package dplyr. La fonction
trouvera automatiquement la variable commune pour faire correspondre les
colonnes de la première et de la seconde table. Dans ce cas,
gene est la variable commune. De telles variables sont
appelées clés. Les clés sont utilisées pour faire correspondre des
observations à travers différentes tables.
R
full_join(rna_mini, annot1)
OUTPUT
Joining with `by = join_by(gene)`
OUTPUT
# A tibble: 10 × 4
gene sample expression gene_description
<chr> <chr> <dbl> <chr>
1 Asl GSM2545336 1170 argininosuccinate lyase [Source:MGI Symbol;Acc…
2 Apod GSM2545336 36194 apolipoprotein D [Source:MGI Symbol;Acc:MGI:88…
3 Cyp2d22 GSM2545336 4060 cytochrome P450, family 2, subfamily d, polype…
4 Klk6 GSM2545336 287 kallikrein related-peptidase 6 [Source:MGI Sym…
5 Fcrls GSM2545336 85 Fc receptor-like S, scavenger receptor [Source…
6 Slc2a4 GSM2545336 782 solute carrier family 2 (facilitated glucose t…
7 Exd2 GSM2545336 1619 exonuclease 3'-5' domain containing 2 [Source:…
8 Gjc2 GSM2545336 288 gap junction protein, gamma 2 [Source:MGI Symb…
9 Plp1 GSM2545336 43217 proteolipid protein (myelin) 1 [Source:MGI Sym…
10 Gnb4 GSM2545336 1071 guanine nucleotide binding protein (G protein)…
En pratique, les annotations géniques sont parfois étiquetées de manière différente.
Le tableau annot2 est exactement identique au tableau
annot1, sauf que la variable contenant les noms de gènes
est nommée différemment. Encore une fois, vous pouvez soit télécharger
annot2.csv vous-même et le déplacer dans data/, soit
utiliser le code R ci-dessous.
R
download.file(url = "https://carpentries-incubator.github.io/bioc-intro/data/annot2.csv",
destfile = "data/annot2.csv")
annot2 <- read_csv(file = "data/annot2.csv")
annot2
OUTPUT
# A tibble: 10 × 2
external_gene_name description
<chr> <chr>
1 Cyp2d22 cytochrome P450, family 2, subfamily d, polypeptide 22 [S…
2 Klk6 kallikrein related-peptidase 6 [Source:MGI Symbol;Acc:MGI…
3 Fcrls Fc receptor-like S, scavenger receptor [Source:MGI Symbol…
4 Plp1 proteolipid protein (myelin) 1 [Source:MGI Symbol;Acc:MGI…
5 Exd2 exonuclease 3'-5' domain containing 2 [Source:MGI Symbol;…
6 Apod apolipoprotein D [Source:MGI Symbol;Acc:MGI:88056]
7 Gnb4 guanine nucleotide binding protein (G protein), beta 4 [S…
8 Slc2a4 solute carrier family 2 (facilitated glucose transporter)…
9 Asl argininosuccinate lyase [Source:MGI Symbol;Acc:MGI:88084]
10 Gjc2 gap junction protein, gamma 2 [Source:MGI Symbol;Acc:MGI:…
Si aucun des noms de variables ne correspond, nous pouvons définir
manuellement les variables à utiliser pour le rapprochement. Ces
variables peuvent être définies à l’aide de l’argument by,
comme illustré ci-dessous avec les tables rna_mini et
annot2.
R
full_join(rna_mini, annot2, by = c("gene" = "external_gene_name"))
OUTPUT
# A tibble: 10 × 4
gene sample expression description
<chr> <chr> <dbl> <chr>
1 Asl GSM2545336 1170 argininosuccinate lyase [Source:MGI Symbol;Acc…
2 Apod GSM2545336 36194 apolipoprotein D [Source:MGI Symbol;Acc:MGI:88…
3 Cyp2d22 GSM2545336 4060 cytochrome P450, family 2, subfamily d, polype…
4 Klk6 GSM2545336 287 kallikrein related-peptidase 6 [Source:MGI Sym…
5 Fcrls GSM2545336 85 Fc receptor-like S, scavenger receptor [Source…
6 Slc2a4 GSM2545336 782 solute carrier family 2 (facilitated glucose t…
7 Exd2 GSM2545336 1619 exonuclease 3'-5' domain containing 2 [Source:…
8 Gjc2 GSM2545336 288 gap junction protein, gamma 2 [Source:MGI Symb…
9 Plp1 GSM2545336 43217 proteolipid protein (myelin) 1 [Source:MGI Sym…
10 Gnb4 GSM2545336 1071 guanine nucleotide binding protein (G protein)…
Comme on peut le voir ci-dessus, le nom de la variable de la première table est conservé dans celle qui a été jointe.
Défi :
Téléchargez le tableau annot3 en cliquant
sur ce lien et placez le tableau dans votre répertoire data/. À
l’aide de la fonction full_join(), joignez les tableaux
rna_mini et annot3. Qu’est-il arrivé aux gènes
Klk6, mt-Tf, mt-Rnr1, mt-Tv,
mt-Rnr2 et mt-Tl1 ?
R
annot3 <- read_csv("data/annot3.csv")
full_join(rna_mini, annot3)
OUTPUT
# A tibble: 15 × 4
gene sample expression gene_description
<chr> <chr> <dbl> <chr>
1 Asl GSM2545336 1170 argininosuccinate lyase [Source:MGI Symbol;Acc…
2 Apod GSM2545336 36194 apolipoprotein D [Source:MGI Symbol;Acc:MGI:88…
3 Cyp2d22 GSM2545336 4060 cytochrome P450, family 2, subfamily d, polype…
4 Klk6 GSM2545336 287 <NA>
5 Fcrls GSM2545336 85 Fc receptor-like S, scavenger receptor [Source…
6 Slc2a4 GSM2545336 782 solute carrier family 2 (facilitated glucose t…
7 Exd2 GSM2545336 1619 exonuclease 3'-5' domain containing 2 [Source:…
8 Gjc2 GSM2545336 288 gap junction protein, gamma 2 [Source:MGI Symb…
9 Plp1 GSM2545336 43217 proteolipid protein (myelin) 1 [Source:MGI Sym…
10 Gnb4 GSM2545336 1071 guanine nucleotide binding protein (G protein)…
11 mt-Tf <NA> NA mitochondrially encoded tRNA phenylalanine [So…
12 mt-Rnr1 <NA> NA mitochondrially encoded 12S rRNA [Source:MGI S…
13 mt-Tv <NA> NA mitochondrially encoded tRNA valine [Source:MG…
14 mt-Rnr2 <NA> NA mitochondrially encoded 16S rRNA [Source:MGI S…
15 mt-Tl1 <NA> NA mitochondrially encoded tRNA leucine 1 [Source…
Le gène Klk6 n’est présent que dans rna_mini,
tandis que les gènes mt-Tf, mt-Rnr1, mt-Tv,
mt-Rnr2 et mt-Tl1 ne figurent que dans le tableau
annot3. Leurs valeurs respectives pour les variables du
tableau ont été codées comme manquantes.
Exportation de données
Maintenant que vous avez appris à utiliser dplyr pour
extraire des informations de vos données brutes ou les résumer, vous
souhaiterez peut-être exporter ces nouveaux jeux de données pour les
partager avec vos collaborateurs ou pour les archiver.
À l’instar de la fonction read_csv() utilisée pour lire
des fichiers CSV dans R, il existe une fonction write_csv()
qui génère des fichiers CSV à partir de tableaux de données.
Avant d’utiliser write_csv(), nous allons créer un
nouveau dossier, data_output, dans notre répertoire de
travail pour y stocker cet ensemble de données généré. Nous ne voulons
pas écrire les ensembles de données générés dans le même répertoire que
nos données brutes. Il est bon de les garder séparés. Le dossier
data ne doit contenir que les données brutes et non
modifiées, et doit rester intouché pour s’assurer que nous ne le
supprimons ni ne le modifions. En revanche, notre script générera le
contenu du répertoire data_output, de sorte que même si les
fichiers qu’il contient sont supprimés, nous pourrons toujours les
régénérer.
Utilisons write_csv() pour enregistrer le tableau
rna_wide que nous avons créé précédemment.
R
write_csv(rna_wide, file = "data_output/rna_wide.csv")
- Données tabulaires en R à l’aide du méta-package tidyverse
Content from Visualisation des données
Last updated on 2026-11-07 | Edit this page
Estimated time: 120 minutes
Overview
Questions
- Visualisation dans R
Objectives
- Créer des nuages de points, des boîtes à moustaches, des graphiques en courbes, etc., à l’aide de ggplot.
- Définir les paramètres globaux des graphiques.
- Décrire le facettage et l’appliquer dans ggplot.
- Modifier l’aspect visuel d’un graphique ggplot existant (y compris les libellés d’axes et la couleur).
- Créer des graphiques complexes et personnalisés à partir de données contenues dans un tableau de données.
Cet épisode est basé sur la leçon Data Analysis and Visualisation in R for Ecologists de Data Carpentries.
Visualisation des données
Nous commençons par charger les packages nécessaires.
ggplot2 est inclus dans le package
tidyverse.
R
library("tidyverse")
Si les données enregistrées lors de la leçon précédente ne sont plus présentes dans l’espace de travail, chargez-les.
R
rna <- read.csv("data/rnaseq.csv")
La fiche
pratique de visualisation de données couvrira les bases et les
fonctionnalités plus avancées de ggplot2, et permettra, en
plus de servir de rappel, d’obtenir un aperçu des nombreuses
représentations de données disponibles dans le package. Les tutoriels
vidéo suivants (partie 1 et partie 2) de
Thomas Lin Pedersen sont également très instructifs.
Graphiques avec ggplot2
ggplot2 est une bibliothèque de graphisme qui permet de
créer facilement des graphiques complexes à partir de données contenues
dans un tableau de données. Elle offre une interface plus programmatique
pour spécifier les variables à tracer, la manière dont elles sont
affichées ainsi que les propriétés visuelles générales. Le fondement
théorique qui sous-tend ggplot2 est la Grammar of
Graphics ( Wilkinson (2005) ). En
utilisant cette approche, nous n’avons besoin que de modifications
minimales si les données sous-jacentes changent ou si nous décidons de
passer d’un graphique en barres à un graphique à dispersion. Cela permet
de créer des graphiques de qualité publication avec un minimum
d’ajustements et de peaufinage.
Il existe un ouvrage sur ggplot2 ( Wickham (2016) ) qui offre un bon aperçu, mais
il est obsolète. La 3e édition est en préparation et sera disponible gratuitement en ligne.
La page web ggplot2 (https://ggplot2.tidyverse.org)
propose une documentation complète.
ggplot2 fonctionne avec des données au format « long »,
c’est-à-dire une colonne pour chaque dimension et une ligne pour chaque
observation. Des données bien structurées vous feront gagner beaucoup de
temps lors de la création de figures avec ggplot2.
Les graphiques ggplot sont construits étape par étape en ajoutant de nouveaux éléments. L’ajout de couches de cette manière permet une grande flexibilité et une personnalisation approfondie des graphiques.
Le principe de la Grammaire des graphiques est que l’on peut construire tout graphique à partir des mêmes 3 composants : (1) un jeu de données, (2) un système de coordonnées et (3) des geoms — c’est-à-dire des marques visuelles qui représentent des points de données 1
Pour créer un ggplot, nous utiliserons le modèle de base suivant, applicable à différents types de graphiques :
ggplot(data = <DATA>, mapping = aes(<MAPPINGS>)) + <GEOM_FUNCTION>()
- utilisez la fonction
ggplot()et liez le graphique à un tableau de données spécifique à l’aide de l’argumentdata
R
ggplot(data = rna)
- définissez une correspondance (avec la fonction
esthétique (
aes)), en sélectionnant les variables à tracer et en précisant comment les représenter dans le graphique, par exemple par les positions x/y ou par des caractéristiques telles que la taille, la forme, la couleur, etc.
R
ggplot(data = rna, mapping = aes(x = expression))
-
ajoutez des « geoms » — géométries, ou représentations graphiques des données dans le graphique (points, lignes, barres).
ggplot2propose de nombreuses geoms différentes ; nous utiliserons aujourd’hui quelques-unes des plus courantes, notamment :* `geom_point()` for scatter plots, dot plots, etc. * `geom_histogram()` for histograms * `geom_boxplot()` for, well, boxplots! * `geom_line()` for trend lines, time series, etc.
Pour ajouter un geom(etry) au graphique, utilisez l’opérateur
+. Utilisons d’abord geom_histogram() :
R
ggplot(data = rna, mapping = aes(x = expression)) +
geom_histogram()
OUTPUT
`stat_bin()` using `bins = 30`. Pick better value `binwidth`.

Le + du package ggplot2 est
particulièrement utile car il permet de modifier des objets
ggplot existants. Cela signifie que vous pouvez facilement
configurer des modèles de graphiques et explorer commodément différents
types de graphiques ; ainsi, le graphique ci-dessus peut également être
généré avec un code comme celui-ci :
R
# Assign plot to a variable
rna_plot <- ggplot(data = rna,
mapping = aes(x = expression))
# Draw the plot
rna_plot + geom_histogram()
Défi
Vous avez probablement remarqué un message automatique qui s’affiche lors du tracé de l’histogramme :
OUTPUT
`stat_bin()` using `bins = 30`. Pick better value `binwidth`.
Modifiez les arguments bins ou binwidth de
geom_histogram() pour modifier le nombre ou la largeur des
intervalles.
R
# change bins
ggplot(rna, aes(x = expression)) +
geom_histogram(bins = 15)

R
# change binwidth
ggplot(rna, aes(x = expression)) +
geom_histogram(binwidth = 2000)

On constate ici que les données sont asymétriques vers la droite.
Nous pouvons appliquer une transformation logarithmique en base 2 pour
obtenir une distribution plus symétrique. Notons que nous ajoutons ici
une petite valeur constante (+1) afin d’éviter que des
valeurs -Inf ne soient renvoyées pour des valeurs
d’expression égales à 0.
R
rna <- rna |>
mutate(expression_log = log2(expression + 1))
Si nous traçons maintenant l’histogramme des expressions transformées en logarithme en base 2, la distribution est effectivement plus proche d’une distribution normale.
R
ggplot(rna, aes(x = expression_log)) + geom_histogram()
OUTPUT
`stat_bin()` using `bins = 30`. Pick better value `binwidth`.

Désormais, nous travaillerons sur les valeurs d’expression transformées par logarithme.
Défi
Une autre façon de visualiser cette transformation consiste à examiner l’échelle des observations. Par exemple, il peut être utile de modifier l’échelle de l’axe afin de mieux répartir les observations dans l’espace du graphique. La modification de l’échelle des axes s’effectue de la même manière que l’ajout ou la modification d’autres composants (c’est-à-dire en ajoutant des commandes progressivement). Essayez d’effectuer cette modification :
- Représentez l’expression non transformée à l’échelle log10 ; voir
scale_x_log10(). Comparez-la au graphique précédent. Pourquoi des messages d’avertissement s’affichent-ils désormais ?
R
ggplot(data = rna,mapping = aes(x = expression))+
geom_histogram() +
scale_x_log10()
WARNING
Warning in scale_x_log10(): log-10 transformation introduced infinite values.
OUTPUT
`stat_bin()` using `bins = 30`. Pick better value `binwidth`.
WARNING
Warning: Removed 507 rows containing non-finite outside the scale range
(`stat_bin()`).

Notes
- Tout ce que vous insérez dans la fonction
ggplot()est visible par toutes les couches geom que vous ajoutez (c’est-à-dire qu’il s’agit de paramètres de tracé globaux). Cela inclut la correspondance des axes x et y que vous configurez dansaes(). - Vous pouvez également spécifier des correspondances pour un geom
donné, indépendamment des correspondances définies globalement dans la
fonction
ggplot(). - Le signe
+utilisé pour ajouter de nouvelles couches doit être placé à la fin de la ligne contenant la couche précédente. Si, en revanche, le signe+est ajouté au début de la ligne contenant la nouvelle couche,ggplot2n’ajoutera pas la nouvelle couche et renvoiera un message d’erreur.
R
# This is the correct syntax for adding layers
rna_plot +
geom_histogram()
# This will not add the new layer and will return an error message
rna_plot
+ geom_histogram()
Création itérative de vos graphiques
Nous allons maintenant tracer un nuage de points avec deux variables
continues et la fonction geom_point(). Ce graphique
représentera les log2 des rapports d’expression (log2 fold changes), en
comparant le temps 8 au temps 0 et le temps 4 au temps 0. Pour cela,
nous devons d’abord calculer les moyennes des valeurs d’expression
transformées en log2, par gène et par temps. Nous calculons ensuite les
log2 des rapports d’expression en soustrayant la moyenne au temps 0 de
celle au temps 8, puis de celle au temps 4. Notez que nous incluons
également le biotype des gènes, que nous utiliserons plus tard pour
représenter les gènes. Nous enregistrerons ces log2 des rapports
d’expression dans un nouveau tableau de données appelé
rna_fc..
R
rna_fc <- rna |> select(gene, time,
gene_biotype, expression_log) |>
group_by(gene, time, gene_biotype) |>
summarize(mean_exp = mean(expression_log)) |>
pivot_wider(names_from = time,
values_from = mean_exp) |>
mutate(time_8_vs_0 = `8` - `0`, time_4_vs_0 = `4` - `0`)
OUTPUT
`summarise()` has regrouped the output.
ℹ Summaries were computed grouped by gene, time, and gene_biotype.
ℹ Output is grouped by gene and time.
ℹ Use `summarise(.groups = "drop_last")` to silence this message.
ℹ Use `summarise(.by = c(gene, time, gene_biotype))` for per-operation grouping
(`?dplyr::dplyr_by`) instead.
Nous pouvons ensuite créer un ggplot avec le jeu de données
rna_fc nouvellement créé. La création de graphiques avec
ggplot2 est généralement un processus itératif. Nous
commençons par définir le jeu de données que nous utiliserons, disposer
les axes et choisir un geom :
R
ggplot(data = rna_fc, mapping = aes(x = time_4_vs_0, y = time_8_vs_0)) +
geom_point()

Ensuite, nous commençons à modifier ce graphique pour en extraire
davantage d’informations. Par exemple, nous pouvons ajouter de la
transparence (alpha) afin d’éviter la superposition des
points :
R
ggplot(data = rna_fc, mapping = aes(x = time_4_vs_0, y = time_8_vs_0)) +
geom_point(alpha = 0.3)

Nous pouvons également ajouter des couleurs pour tous les points :
R
ggplot(data = rna_fc, mapping = aes(x = time_4_vs_0, y = time_8_vs_0)) +
geom_point(alpha = 0.3, color = "blue")

Ou encore, pour colorer chaque gène du graphique différemment, vous
pourriez utiliser un vecteur comme entrée pour l’argument
color. ggplot2 fournira une couleur
différente correspondant à différentes valeurs du vecteur. Voici un
exemple où nous colorions avec gene_biotype :
R
ggplot(data = rna_fc, mapping = aes(x = time_4_vs_0, y = time_8_vs_0)) +
geom_point(alpha = 0.3, aes(color = gene_biotype))

Nous pouvons également spécifier les couleurs directement au sein de
la correspondance fournie dans la fonction ggplot().
Celles-ci seront prises en compte par toutes les couches geom, et la
correspondance sera déterminée par les axes x et y configurés dans
aes().
R
ggplot(data = rna_fc, mapping = aes(x = time_4_vs_0, y = time_8_vs_0,
color = gene_biotype)) +
geom_point(alpha = 0.3)

Enfin, nous pourrions également ajouter une ligne diagonale avec la
fonction geom_abline() :
R
ggplot(data = rna_fc, mapping = aes(x = time_4_vs_0, y = time_8_vs_0,
color = gene_biotype)) +
geom_point(alpha = 0.3) +
geom_abline(intercept = 0)

Notons que nous pouvons modifier la couche geom de
geom_point à geom_jitter et que les couleurs
resteront déterminées par gene_biotype.
R
ggplot(data = rna_fc, mapping = aes(x = time_4_vs_0, y = time_8_vs_0,
color = gene_biotype)) +
geom_jitter(alpha = 0.3) +
geom_abline(intercept = 0)

Défi
Les nuages de points peuvent être des outils exploratoires utiles
pour de petits jeux de données. Pour les jeux de données comportant un
grand nombre d’observations, comme le jeu de données
rna_fc, la superposition des points peut constituer une
limite. Une stratégie pour gérer de tels cas consiste à regrouper les
observations dans des cellules hexagonales. L’espace du graphique est
pavé d’hexagones. Une couleur est attribuée à chaque hexagone en
fonction du nombre d’observations qu’il contient.
Pour regrouper les observations dans des cellules hexagonales avec
ggplot2, installez d’abord le package Rhexbindepuis CRAN et chargez-le.Utilisez ensuite la fonction
geom_hex()pour générer la figure hexbin.Quels sont les avantages et les inconvénients d’un graphique à cellules hexagonales par rapport à un nuage de points ? Examinez le nuage de points ci-dessus et comparez-le au graphique à cellules hexagonales que vous avez créé.
R
install.packages("hexbin")
R
library("hexbin")
ggplot(data = rna_fc, mapping = aes(x = time_4_vs_0, y = time_8_vs_0)) +
geom_hex() +
geom_abline(intercept = 0)

Défi
Utilisez ce que vous venez d’apprendre pour créer un graphique de
dispersion de expression_log en fonction de
sample à partir du jeu de données rna, en
affichant le temps dans différentes couleurs. Est-ce un bon moyen de
présenter ce type de données ?
R
ggplot(data = rna, mapping = aes(y = expression_log, x = sample)) +
geom_point(aes(color = time))

Diagramme en boîtes
Nous pouvons utiliser des boîtes à moustaches pour visualiser la distribution des expressions géniques au sein de chaque échantillon :
R
ggplot(data = rna,
mapping = aes(y = expression_log, x = sample)) +
geom_boxplot()

En ajoutant des points au graphique en boîtes, nous pouvons mieux appréhender le nombre de mesures et leur répartition :
R
ggplot(data = rna,
mapping = aes(y = expression_log, x = sample)) +
geom_jitter(alpha = 0.2, color = "tomato") +
geom_boxplot(alpha = 0)

Défi
Remarquez que la couche du boxplot se trouve devant la couche du jitter. Que faut-il modifier dans le code pour placer le boxplot sous les points ?
Nous devrions inverser l’ordre de ces deux geoms :
R
ggplot(data = rna,
mapping = aes(y = expression_log, x = sample)) +
geom_boxplot(alpha = 0) +
geom_jitter(alpha = 0.2, color = "tomato")

Vous remarquerez peut-être que les valeurs sur l’axe des abscisses sont toujours mal lisibles. Modifions l’orientation des étiquettes et ajustons-les verticalement et horizontalement pour qu’elles ne se chevauchent pas. Vous pouvez utiliser un angle de 90 degrés, ou expérimenter pour trouver l’angle approprié pour des étiquettes orientées en diagonale :
R
ggplot(data = rna,
mapping = aes(y = expression_log, x = sample)) +
geom_jitter(alpha = 0.2, color = "tomato") +
geom_boxplot(alpha = 0) +
theme(axis.text.x = element_text(angle = 90, hjust = 0.5, vjust = 0.5))

Défi
Ajoutez de la couleur aux points de votre graphique en boîtes en
fonction de la durée de l’infection (time).
Indice : Vérifiez la classe de time. Envisagez
de modifier la classe de time, passant de nombre entier à
facteur, directement dans la correspondance ggplot. Pourquoi ce
changement modifie-t-il la façon dont R crée le graphique ?
R
# time as integer
ggplot(data = rna,
mapping = aes(y = expression_log,
x = sample)) +
geom_jitter(alpha = 0.2, aes(color = time)) +
geom_boxplot(alpha = 0) +
theme(axis.text.x = element_text(angle = 90, hjust = 0.5, vjust = 0.5))

R
# time as factor
ggplot(data = rna,
mapping = aes(y = expression_log,
x = sample)) +
geom_jitter(alpha = 0.2, aes(color = as.factor(time))) +
geom_boxplot(alpha = 0) +
theme(axis.text.x = element_text(angle = 90, hjust = 0.5, vjust = 0.5))

Défi
Les boîtes à moustaches sont des résumés utiles, mais masquent la forme de la distribution. Par exemple, si la distribution est bimodale, nous ne la verrions pas dans une boîte à moustaches. Une alternative à la boîte à moustaches est le graphique en violon, où la forme (de la densité des points) est tracée.
- Remplacez le graphique en boîtes par un graphique en violons ; voir
geom_violin(). Remplissez les violons en fonction du temps à l’aide de l’argumentfill.
R
ggplot(data = rna,
mapping = aes(y = expression_log, x = sample)) +
geom_violin(aes(fill = as.factor(time))) +
theme(axis.text.x = element_text(angle = 90, hjust = 0.5, vjust = 0.5))

Défi
- Modifiez le graphique en violons pour remplir les violons par
sex.
R
ggplot(data = rna,
mapping = aes(y = expression_log, x = sample)) +
geom_violin(aes(fill = sex)) +
theme(axis.text.x = element_text(angle = 90, hjust = 0.5, vjust = 0.5))

Graphiques en courbes
Calculons l’expression moyenne par durée d’infection pour les 10
gènes présentant les log2 des rapports d’expression les plus élevés
entre le temps 8 et le temps 0. Tout d’abord, nous devons sélectionner
les gènes et créer un sous-ensemble de rna appelé
sub_rna contenant les 10 gènes sélectionnés, puis regrouper
les données et calculer l’expression génique moyenne au sein de chaque
groupe :
R
rna_fc <- rna_fc |> arrange(desc(time_8_vs_0))
genes_selected <- rna_fc$gene[1:10]
sub_rna <- rna |>
filter(gene %in% genes_selected)
mean_exp_by_time <- sub_rna |>
group_by(gene,time) |>
summarize(mean_exp = mean(expression_log))
OUTPUT
`summarise()` has regrouped the output.
ℹ Summaries were computed grouped by gene and time.
ℹ Output is grouped by gene.
ℹ Use `summarise(.groups = "drop_last")` to silence this message.
ℹ Use `summarise(.by = c(gene, time))` for per-operation grouping
(`?dplyr::dplyr_by`) instead.
R
mean_exp_by_time
OUTPUT
# A tibble: 30 × 3
# Groups: gene [10]
gene time mean_exp
<chr> <int> <dbl>
1 Acr 0 5.07
2 Acr 4 5.54
3 Acr 8 7.31
4 Aipl1 0 3.70
5 Aipl1 4 3.89
6 Aipl1 8 6.56
7 Bst1 0 3.20
8 Bst1 4 3.77
9 Bst1 8 5.22
10 Chil3 0 4.00
# ℹ 20 more rows
Nous pouvons créer le graphique en courbes avec la durée de l’infection sur l’axe des abscisses et l’expression moyenne sur l’axe des ordonnées :
R
ggplot(data = mean_exp_by_time, mapping = aes(x = time, y = mean_exp)) +
geom_line()

Malheureusement, cela ne fonctionne pas car nous avons tracé les
données de tous les gènes ensemble. Nous devons indiquer à ggplot de
tracer une ligne pour chaque gène en modifiant la fonction esthétique
pour y inclure group = gene :
R
ggplot(data = mean_exp_by_time,
mapping = aes(x = time, y = mean_exp, group = gene)) +
geom_line()

Nous pourrons distinguer les gènes dans le graphique si nous ajoutons
des couleurs (l’utilisation de color regroupe également
automatiquement les données) :
R
ggplot(data = mean_exp_by_time,
mapping = aes(x = time, y = mean_exp, color = gene)) +
geom_line()

Facettage
ggplot2 dispose d’une technique appelée
facettage qui permet de diviser un graphique en plusieurs
sous-graphiques selon un facteur du jeu de données. Ces différents
sous-graphiques héritent des mêmes propriétés (limites des axes,
graduations, etc.) afin de faciliter leur comparaison directe. Nous
l’utiliserons pour créer un graphique en courbes au fil du temps pour
chaque gène :
R
ggplot(data = mean_exp_by_time,
mapping = aes(x = time, y = mean_exp)) + geom_line() +
facet_wrap(~ gene)

Ici, les axes x et y ont tous deux la même échelle pour tous les
sous-graphiques. Vous pouvez modifier ce comportement par défaut en
modifiant scales afin de permettre une échelle libre pour
l’axe y :
R
ggplot(data = mean_exp_by_time,
mapping = aes(x = time, y = mean_exp)) +
geom_line() +
facet_wrap(~ gene, scales = "free_y")

Nous souhaitons maintenant séparer la ligne dans chaque graphique
selon le sexe des souris. Pour ce faire, nous devons calculer
l’expression moyenne dans le tableau de données, regroupé par
gene, time et sex :
R
mean_exp_by_time_sex <- sub_rna |>
group_by(gene, time, sex) |>
summarize(mean_exp = mean(expression_log))
OUTPUT
`summarise()` has regrouped the output.
ℹ Summaries were computed grouped by gene, time, and sex.
ℹ Output is grouped by gene and time.
ℹ Use `summarise(.groups = "drop_last")` to silence this message.
ℹ Use `summarise(.by = c(gene, time, sex))` for per-operation grouping
(`?dplyr::dplyr_by`) instead.
R
mean_exp_by_time_sex
OUTPUT
# A tibble: 60 × 4
# Groups: gene, time [30]
gene time sex mean_exp
<chr> <int> <chr> <dbl>
1 Acr 0 Female 5.13
2 Acr 0 Male 5.00
3 Acr 4 Female 5.93
4 Acr 4 Male 5.15
5 Acr 8 Female 7.27
6 Acr 8 Male 7.36
7 Aipl1 0 Female 3.67
8 Aipl1 0 Male 3.73
9 Aipl1 4 Female 4.07
10 Aipl1 4 Male 3.72
# ℹ 50 more rows
Nous pouvons désormais créer le graphique facetté en effectuant un
nouveau découpage selon le sexe à l’aide de color (au sein
d’un même graphique) :
R
ggplot(data = mean_exp_by_time_sex,
mapping = aes(x = time, y = mean_exp, color = sex)) +
geom_line() +
facet_wrap(~ gene, scales = "free_y")

En général, les graphiques à fond blanc sont plus lisibles une fois
imprimés. Nous pouvons régler le fond sur blanc à l’aide de la fonction
theme_bw(). De plus, nous pouvons supprimer la grille :
R
ggplot(data = mean_exp_by_time_sex,
mapping = aes(x = time, y = mean_exp, color = sex)) +
geom_line() +
facet_wrap(~ gene, scales = "free_y") +
theme_bw() +
theme(panel.grid = element_blank())

Défi
Utilisez ce que vous venez d’apprendre pour créer un graphique illustrant l’évolution de l’expression moyenne de chaque chromosome au cours de l’infection.
R
mean_exp_by_chromosome <- rna |>
group_by(chromosome_name, time) |>
summarize(mean_exp = mean(expression_log))
OUTPUT
`summarise()` has regrouped the output.
ℹ Summaries were computed grouped by chromosome_name and time.
ℹ Output is grouped by chromosome_name.
ℹ Use `summarise(.groups = "drop_last")` to silence this message.
ℹ Use `summarise(.by = c(chromosome_name, time))` for per-operation grouping
(`?dplyr::dplyr_by`) instead.
R
ggplot(data = mean_exp_by_chromosome, mapping = aes(x = time,
y = mean_exp)) +
geom_line() +
facet_wrap(~ chromosome_name, scales = "free_y")

La fonction facet_wrap répartit les facettes sur
plusieurs lignes et colonnes afin qu’elles tiennent clairement sur une
seule page. La fonction facet_grid permet, quant à elle, de
spécifier explicitement la disposition des facettes à l’aide d’une
formule (rows ~ columns ; un . peut servir de
marqueur pour indiquer une seule ligne ou une seule colonne).
Modifions le graphique précédent pour comparer l’évolution de la moyenne de l’expression génique chez les mâles et les femelles au fil du temps :
R
# One column, facet by rows
ggplot(data = mean_exp_by_time_sex,
mapping = aes(x = time, y = mean_exp, color = gene)) +
geom_line() +
facet_grid(sex ~ .)

R
# One row, facet by column
ggplot(data = mean_exp_by_time_sex,
mapping = aes(x = time, y = mean_exp, color = gene)) +
geom_line() +
facet_grid(. ~ sex)

Thèmes de ggplot2
En plus de theme_bw(), qui change l’arrière-plan du
graphique en blanc, ggplot2 propose plusieurs autres thèmes
qui peuvent s’avérer utiles pour modifier rapidement l’aspect de votre
visualisation. La liste complète des thèmes est disponible à https://ggplot2.tidyverse.org/reference/ggtheme.html.
theme_minimal() et theme_light() sont
populaires, et theme_void() peut être utile comme point de
départ pour créer un nouveau thème personnalisé.
Le package ggthemes
propose une grande variété d’options (dont un thème Excel 2003). Le site web des extensions
ggplot2 propose une liste de packages qui étendent les
fonctionnalités de ggplot2, notamment des thèmes
supplémentaires.
Personnalisation
Revenons au graphique facetté de l’expression moyenne selon le temps et le gène, coloré par sexe.
Jetez un coup d’œil à la fiche
pratique ggplot2, et réfléchissez à des moyens
d’améliorer le graphique.
Désormais, nous pouvons remplacer les noms des axes par des appellations plus informatives que « time » et « mean_exp », et ajouter un titre à la figure :
R
ggplot(data = mean_exp_by_time_sex,
mapping = aes(x = time, y = mean_exp, color = sex)) +
geom_line() +
facet_wrap(~ gene, scales = "free_y") +
theme_bw() +
theme(panel.grid = element_blank()) +
labs(title = "Mean gene expression by duration of the infection",
x = "Duration of the infection (in days)",
y = "Mean gene expression")

Les axes possèdent des noms plus explicites, mais leur lisibilité peut être améliorée en augmentant la taille de la police :
R
ggplot(data = mean_exp_by_time_sex,
mapping = aes(x = time, y = mean_exp, color = sex)) +
geom_line() +
facet_wrap(~ gene, scales = "free_y") +
theme_bw() +
theme(panel.grid = element_blank()) +
labs(title = "Mean gene expression by duration of the infection",
x = "Duration of the infection (in days)",
y = "Mean gene expression") +
theme(text = element_text(size = 16))

Notez qu’il est également possible de modifier les polices de vos
graphiques. Si vous utilisez Windows, vous devrez peut-être installer le
package
extrafont.
Nous pouvons encore personnaliser la couleur du texte des axes X et
Y, la couleur de la grille, etc. Nous pouvons également, par exemple,
déplacer la légende en haut en définissant legend.position
à "top".
R
ggplot(data = mean_exp_by_time_sex,
mapping = aes(x = time, y = mean_exp, color = sex)) +
geom_line() +
facet_wrap(~ gene, scales = "free_y") +
theme_bw() +
theme(panel.grid = element_blank()) +
labs(title = "Mean gene expression by duration of the infection",
x = "Duration of the infection (in days)",
y = "Mean gene expression") +
theme(text = element_text(size = 16),
axis.text.x = element_text(colour = "royalblue4", size = 12),
axis.text.y = element_text(colour = "royalblue4", size = 12),
panel.grid = element_line(colour="lightsteelblue1"),
legend.position = "top")

Si vous préférez votre personnalisation au thème par défaut, vous pouvez l’enregistrer sous la forme d’un objet afin de l’appliquer facilement à d’autres graphiques. Voici un exemple avec l’histogramme que nous avons créé précédemment.
R
blue_theme <- theme(axis.text.x = element_text(colour = "royalblue4",
size = 12),
axis.text.y = element_text(colour = "royalblue4",
size = 12),
text = element_text(size = 16),
panel.grid = element_line(colour="lightsteelblue1"))
ggplot(rna, aes(x = expression_log)) +
geom_histogram(bins = 20) +
blue_theme

Défi
Avec toutes ces informations en main, prenez encore cinq minutes pour
soit améliorer l’un des graphiques générés dans cet exercice, soit créer
votre propre graphique esthétique. Consultez la fiche
de référence ggplot2 de RStudio pour vous inspirer.
Voici quelques idées :
- Voyez si vous pouvez modifier l’épaisseur des lignes.
- Pouvez-vous trouver un moyen de modifier le nom de la légende ? Et
pour ses étiquettes ? (indice : cherchez une fonction ggplot commençant
par
scale_) - Essayez d’utiliser une autre palette de couleurs ou de spécifier manuellement les couleurs des lignes (voir https://www.cookbook-r.com/Graphs/Colors_(ggplot2)/).
Par exemple, en se basant sur ce graphique :
R
ggplot(data = mean_exp_by_time_sex,
mapping = aes(x = time, y = mean_exp, color = sex)) +
geom_line() +
facet_wrap(~ gene, scales = "free_y") +
theme_bw() +
theme(panel.grid = element_blank())

Nous pouvons le personnaliser de la manière suivante :
R
# change the thickness of the lines
ggplot(data = mean_exp_by_time_sex,
mapping = aes(x = time, y = mean_exp, color = sex)) +
geom_line(size=1.5) +
facet_wrap(~ gene, scales = "free_y") +
theme_bw() +
theme(panel.grid = element_blank())
WARNING
Warning: Using `size` aesthetic for lines was deprecated in ggplot2 3.4.0.
ℹ Please use `linewidth` instead.
This warning is displayed once per session.
Call `lifecycle::last_lifecycle_warnings()` to see where this warning was
generated.

R
# change the name of the legend and the labels
ggplot(data = mean_exp_by_time_sex,
mapping = aes(x = time, y = mean_exp, color = sex)) +
geom_line() +
facet_wrap(~ gene, scales = "free_y") +
theme_bw() +
theme(panel.grid = element_blank()) +
scale_color_discrete(name = "Gender", labels = c("F", "M"))

R
# using a different color palette
ggplot(data = mean_exp_by_time_sex,
mapping = aes(x = time, y = mean_exp, color = sex)) +
geom_line() +
facet_wrap(~ gene, scales = "free_y") +
theme_bw() +
theme(panel.grid = element_blank()) +
scale_color_brewer(name = "Gender", labels = c("F", "M"), palette = "Dark2")

R
# manually specifying the colors
ggplot(data = mean_exp_by_time_sex,
mapping = aes(x = time, y = mean_exp, color = sex)) +
geom_line() +
facet_wrap(~ gene, scales = "free_y") +
theme_bw() +
theme(panel.grid = element_blank()) +
scale_color_manual(name = "Gender", labels = c("F", "M"),
values = c("royalblue", "deeppink"))

Composer des graphiques
Le facettage est un excellent outil pour diviser un graphique en plusieurs sous-graphiques, mais il arrive que vous souhaitiez créer une seule figure contenant plusieurs graphiques indépendants, c’est-à-dire fondés sur des variables différentes ou même sur des tableaux de données distincts.
Commençons par créer les deux graphiques que nous souhaitons disposer côte à côte :
Le premier graphique compte le nombre de gènes uniques par
chromosome. Nous devons d’abord réordonner les niveaux de
chromosome_name et filtrer les gènes uniques par
chromosome. Nous modifions également l’échelle de l’axe des ordonnées
pour passer à une échelle logarithmique en base 10, afin d’améliorer la
lisibilité.
R
rna$chromosome_name <- factor(rna$chromosome_name,
levels = c(1:19,"X","Y"))
count_gene_chromosome <- rna |>
select(chromosome_name, gene) |>
distinct() |> ggplot() +
geom_bar(aes(x = chromosome_name), fill = "seagreen",
position = "dodge", stat = "count") +
labs(y = "log10(n genes)", x = "chromosome") +
scale_y_log10()
count_gene_chromosome

Ci-dessous, nous supprimons également entièrement la légende en
définissant legend.position à "none".
R
exp_boxplot_sex <- ggplot(rna, aes(y=expression_log, x = as.factor(time),
color=sex)) +
geom_boxplot(alpha = 0) +
labs(y = "Mean gene exp",
x = "time") + theme(legend.position = "none")
exp_boxplot_sex

Le package patchwork
propose une approche élégante pour combiner des figures en utilisant
+ pour les disposer (généralement côte à côte). Plus
précisément, | les dispose explicitement côte à côte et
/ les empile les uns sur les autres.
R
install.packages("patchwork")
R
library("patchwork")
count_gene_chromosome + exp_boxplot_sex

R
## or count_gene_chromosome | exp_boxplot_sex
R
count_gene_chromosome / exp_boxplot_sex

Nous pouvons affiner davantage le contrôle de la mise en page de la
composition finale à l’aide de plot_layout pour créer des
mises en page plus complexes :
R
count_gene_chromosome + exp_boxplot_sex + plot_layout(ncol = 1)

R
count_gene_chromosome +
(count_gene_chromosome + exp_boxplot_sex) +
exp_boxplot_sex +
plot_layout(ncol = 1)

Le dernier graphique peut également être créé à l’aide des composants
| et / :
R
count_gene_chromosome /
(count_gene_chromosome | exp_boxplot_sex) /
exp_boxplot_sex

Pour en savoir plus sur patchwork, consultez sa page web ou cette vidéo.
Une autre option est le package
gridExtra, qui permet de combiner des
ggplots distincts en une seule figure à l’aide de
grid.arrange() :
R
install.packages("gridExtra")
R
library("gridExtra")
grid.arrange(count_gene_chromosome, exp_boxplot_sex, ncol = 2)

En plus des arguments ncol et nrow,
utilisés pour réaliser des dispositions simples, il existe des outils
permettant de construire
des mises en page plus complexes.
Exportation de graphiques
Une fois votre graphique créé, vous pouvez l’enregistrer dans un fichier au format de votre choix. L’onglet Exportation du volet Plot dans RStudio enregistre vos graphiques à faible résolution, ce qui ne sera pas accepté par de nombreuses revues et ne sera pas adapté aux posters.
Utilisez plutôt la fonction ggsave(), qui vous permet de
modifier facilement la dimension et la résolution de votre graphique en
ajustant les arguments correspondants (width,
height et dpi).
Assurez-vous d’avoir le dossier fig_output/ dans votre
répertoire de travail.
R
my_plot <- ggplot(data = mean_exp_by_time_sex,
mapping = aes(x = time, y = mean_exp, color = sex)) +
geom_line() +
facet_wrap(~ gene, scales = "free_y") +
labs(title = "Mean gene expression by duration of the infection",
x = "Duration of the infection (in days)",
y = "Mean gene expression") +
guides(color=guide_legend(title="Gender")) +
theme_bw() +
theme(axis.text.x = element_text(colour = "royalblue4", size = 12),
axis.text.y = element_text(colour = "royalblue4", size = 12),
text = element_text(size = 16),
panel.grid = element_line(colour="lightsteelblue1"),
legend.position = "top")
ggsave("fig_output/mean_exp_by_time_sex.png", my_plot, width = 15,
height = 10)
# This also works for grid.arrange() plots
combo_plot <- grid.arrange(count_gene_chromosome, exp_boxplot_sex,
ncol = 2, widths = c(4, 6))
ggsave("fig_output/combo_plot_chromosome_sex.png", combo_plot,
width = 10, dpi = 300)
Remarque : Les paramètres width et height
déterminent également la taille de la police dans le graphique
enregistré.
Autres packages de visualisation
ggplot2 est un package très puissant qui s’intègre
parfaitement à notre pipeline de données ordonnées et
d’outils ordonnés. Il existe d’autres packages de visualisation
dans R qu’il ne faut pas négliger.
Graphismes de base
Le système graphique par défaut fourni avec R, souvent appelé
graphismes R de base, est simple et rapide. Il repose sur le
modèle du peintre ou de la toile, où différentes sorties sont
superposées directement les unes aux autres (voir figure ci-dessous ). C’est une différence
fondamentale avec ggplot2 (et avec lattice,
décrit ci-dessous), qui renvoie des objets dédiés, rendus à l’écran ou
dans un fichier, et qui peuvent même être mis à jour.
R
par(mfrow = c(1, 3))
plot(1:20, main = "First layer, produced with plot(1:20)")
plot(1:20, main = "A horizontal red line, added with abline(h = 10)")
abline(h = 10, col = "red")
plot(1:20, main = "A rectangle, added with rect(5, 5, 15, 15)")
abline(h = 10, col = "red")
rect(5, 5, 15, 15, lwd = 3)

Une autre différence majeure est que la fonction de tracé des
graphiques de base tente de faire la bonne chose en fonction du
type d’entrée, c’est-à-dire qu’elle adapte son comportement en fonction
de la classe de son entrée. Cela diffère encore grandement de ce que
l’on trouve dans ggplot2, qui n’accepte que les tableaux de
données en entrée et nécessite que les graphiques soient construits
petit à petit.
R
par(mfrow = c(2, 2))
boxplot(rnorm(100),
main = "Boxplot of rnorm(100)")
boxplot(matrix(rnorm(100), ncol = 10),
main = "Boxplot of matrix(rnorm(100), ncol = 10)")
hist(rnorm(100))
hist(matrix(rnorm(100), ncol = 10))

L’approche par défaut des graphiques de base peut s’avérer très
efficace pour des figures simples et standard, qui peuvent être
produites très rapidement avec une seule ligne de code et une seule
fonction telle que plot, ou hist, ou
boxplot, … Les paramètres par défaut ne sont cependant pas
toujours les plus attrayants, et le réglage des figures, surtout
lorsqu’elles deviennent plus complexes (par exemple pour produire des
facettes), peut s’avérer long et fastidieux.
Le package lattice
Le package lattice ressemble à
ggplot2 en ce qu’il utilise des tableaux de données en
entrée, restitue des objets graphiques et prend en charge le facettage.
lattice, en revanche, ne repose pas sur la grammaire
graphique et possède une interface plus complexe.
Une bonne référence pour le package lattice est Deepayan (2008).
- Visualisation dans R
Source : Data Visualization Cheat Sheet.↩︎
Content from Prochaines étapes
Last updated on 2026-11-07 | Edit this page
Estimated time: 90 minutes
Overview
Questions
- Qu’est-ce qu’un
SummarizedExperiment? - Qu’est-ce que Bioconductor ?
Objectives
- Présentez le projet Bioconductor.
- Présenter la notion de conteneurs de données.
- Présentez un aperçu du
SummarizedExperiment, largement utilisé dans les analyses omiques.
Prochaines étapes
Les données en bioinformatique sont souvent complexes. Pour y remédier, les développeurs définissent des conteneurs de données spécialisés (appelés classes) qui correspondent aux propriétés des données qu’ils doivent traiter.
Cet aspect est central pour le projet Bioconductor1, qui utilise la même infrastructure de données de base à travers ses différents packages. Cela a certainement contribué au succès de Bioconductor. Les développeurs de packages Bioconductor sont invités à utiliser l’infrastructure existante afin d’assurer la cohérence, l’interopérabilité et la stabilité du projet dans son ensemble.
Pour illustrer un tel conteneur de données omiques, nous présenterons
la classe SummarizedExperiment.
SummarizedExperiment
La figure ci-dessous représente l’architecture de la classe SummarizedExperiment.
Les objets de la classe SummarizedExperiment contiennent :
Un ou plusieurs tableaux de mesures (assays) contenant les données omiques quantitatives (données d’expression), stockées sous la forme d’un objet de type matrice. Les caractéristiques mesurées (gènes, transcrits, protéines, etc.) correspondent aux lignes, et les échantillons aux colonnes.
Un emplacement (slot) de métadonnées des échantillons contenant leurs covariables, stockées sous la forme d’un tableau de données. Les lignes de ce tableau représentent les échantillons et correspondent exactement aux colonnes des données d’expression.
Un emplacement (slot) de métadonnées des caractéristiques mesurées contenant leurs covariables, stockées sous la forme d’un tableau de données. Les lignes de ce tableau correspondent exactement aux lignes des données d’expression.
La nature coordonnée de SummarizedExperiment garantit
que les dimensions des différents emplacements (slots) restent
cohérentes lors de la manipulation des données : les colonnes des
données d’expression correspondent aux lignes des métadonnées des
échantillons, tandis que les lignes des données d’expression
correspondent aux lignes des métadonnées des caractéristiques mesurées.
Par exemple, si nous excluons un échantillon du tableau de mesures, il
est automatiquement supprimé des métadonnées des échantillons lors de la
même opération.
Les slots de métadonnées peuvent accueillir des covariables (colonnes) supplémentaires sans affecter les autres structures.
Création d’un SummarizedExperiment
Afin de créer un SummarizedExperiment, nous créerons les
composants individuels, à savoir la matrice de comptage, ainsi que les
métadonnées des échantillons et des gènes à partir de fichiers CSV.
C’est généralement ainsi que les données RNA-Seq sont fournies (après
traitement des données brutes).
-
Une matrice d’expression : nous chargeons la
matrice de comptage en précisant que la première colonne contient les
noms des lignes (les gènes), puis convertissons le
data.frameenmatrix. Vous pouvez la télécharger en cliquant sur ce lien.
R
count_matrix <- read.csv("data/count_matrix.csv",
row.names = 1) |>
as.matrix()
count_matrix[1:5, ]
OUTPUT
GSM2545336 GSM2545337 GSM2545338 GSM2545339 GSM2545340 GSM2545341
Asl 1170 361 400 586 626 988
Apod 36194 10347 9173 10620 13021 29594
Cyp2d22 4060 1616 1603 1901 2171 3349
Klk6 287 629 641 578 448 195
Fcrls 85 233 244 237 180 38
GSM2545342 GSM2545343 GSM2545344 GSM2545345 GSM2545346 GSM2545347
Asl 836 535 586 597 938 1035
Apod 24959 13668 13230 15868 27769 34301
Cyp2d22 3122 2008 2254 2277 2985 3452
Klk6 186 1101 537 567 327 233
Fcrls 68 375 199 177 89 67
GSM2545348 GSM2545349 GSM2545350 GSM2545351 GSM2545352 GSM2545353
Asl 494 481 666 937 803 541
Apod 11258 11812 15816 29242 20415 13682
Cyp2d22 1883 2014 2417 3678 2920 2216
Klk6 742 881 828 250 798 710
Fcrls 300 233 231 81 303 285
GSM2545354 GSM2545362 GSM2545363 GSM2545380
Asl 473 748 576 1192
Apod 11088 15916 11166 38148
Cyp2d22 1821 2842 2011 4019
Klk6 894 501 598 259
Fcrls 248 179 184 68
R
dim(count_matrix)
OUTPUT
[1] 1474 22
- Une table décrivant les échantillons, disponible à ce lien.
R
sample_metadata <- read.csv("data/sample_metadata.csv")
sample_metadata
OUTPUT
sample organism age sex infection strain time tissue mouse
1 GSM2545336 Mus musculus 8 Female InfluenzaA C57BL/6 8 Cerebellum 14
2 GSM2545337 Mus musculus 8 Female NonInfected C57BL/6 0 Cerebellum 9
3 GSM2545338 Mus musculus 8 Female NonInfected C57BL/6 0 Cerebellum 10
4 GSM2545339 Mus musculus 8 Female InfluenzaA C57BL/6 4 Cerebellum 15
5 GSM2545340 Mus musculus 8 Male InfluenzaA C57BL/6 4 Cerebellum 18
6 GSM2545341 Mus musculus 8 Male InfluenzaA C57BL/6 8 Cerebellum 6
7 GSM2545342 Mus musculus 8 Female InfluenzaA C57BL/6 8 Cerebellum 5
8 GSM2545343 Mus musculus 8 Male NonInfected C57BL/6 0 Cerebellum 11
9 GSM2545344 Mus musculus 8 Female InfluenzaA C57BL/6 4 Cerebellum 22
10 GSM2545345 Mus musculus 8 Male InfluenzaA C57BL/6 4 Cerebellum 13
11 GSM2545346 Mus musculus 8 Male InfluenzaA C57BL/6 8 Cerebellum 23
12 GSM2545347 Mus musculus 8 Male InfluenzaA C57BL/6 8 Cerebellum 24
13 GSM2545348 Mus musculus 8 Female NonInfected C57BL/6 0 Cerebellum 8
14 GSM2545349 Mus musculus 8 Male NonInfected C57BL/6 0 Cerebellum 7
15 GSM2545350 Mus musculus 8 Male InfluenzaA C57BL/6 4 Cerebellum 1
16 GSM2545351 Mus musculus 8 Female InfluenzaA C57BL/6 8 Cerebellum 16
17 GSM2545352 Mus musculus 8 Female InfluenzaA C57BL/6 4 Cerebellum 21
18 GSM2545353 Mus musculus 8 Female NonInfected C57BL/6 0 Cerebellum 4
19 GSM2545354 Mus musculus 8 Male NonInfected C57BL/6 0 Cerebellum 2
20 GSM2545362 Mus musculus 8 Female InfluenzaA C57BL/6 4 Cerebellum 20
21 GSM2545363 Mus musculus 8 Male InfluenzaA C57BL/6 4 Cerebellum 12
22 GSM2545380 Mus musculus 8 Female InfluenzaA C57BL/6 8 Cerebellum 19
R
dim(sample_metadata)
OUTPUT
[1] 22 9
- Une table décrivant les gènes, disponible à ce lien.
R
gene_metadata <- read.csv("data/gene_metadata.csv")
gene_metadata[1:10, 1:4]
OUTPUT
gene ENTREZID
1 Asl 109900
2 Apod 11815
3 Cyp2d22 56448
4 Klk6 19144
5 Fcrls 80891
6 Slc2a4 20528
7 Exd2 97827
8 Gjc2 118454
9 Plp1 18823
10 Gnb4 14696
product
1 argininosuccinate lyase, transcript variant X1
2 apolipoprotein D, transcript variant 3
3 cytochrome P450, family 2, subfamily d, polypeptide 22, transcript variant 2
4 kallikrein related-peptidase 6, transcript variant 2
5 Fc receptor-like S, scavenger receptor, transcript variant X1
6 solute carrier family 2 (facilitated glucose transporter), member 4
7 exonuclease 3'-5' domain containing 2
8 gap junction protein, gamma 2, transcript variant 1
9 proteolipid protein (myelin) 1, transcript variant 1
10 guanine nucleotide binding protein (G protein), beta 4, transcript variant X2
ensembl_gene_id
1 ENSMUSG00000025533
2 ENSMUSG00000022548
3 ENSMUSG00000061740
4 ENSMUSG00000050063
5 ENSMUSG00000015852
6 ENSMUSG00000018566
7 ENSMUSG00000032705
8 ENSMUSG00000043448
9 ENSMUSG00000031425
10 ENSMUSG00000027669
R
dim(gene_metadata)
OUTPUT
[1] 1474 9
Nous créerons un SummarizedExperiment à partir de ces
tableaux :
La matrice de comptage qui sera utilisée comme
assayLe tableau décrivant les échantillons sera utilisé comme slot métadonnées des échantillons
Le tableau décrivant les gènes sera utilisé comme slot métadonnées des caractéristiques
Pour ce faire, nous pouvons assembler les différentes parties à
l’aide du constructeur SummarizedExperiment :
R
## BiocManager::install("SummarizedExperiment")
library("SummarizedExperiment")
Tout d’abord, nous nous assurons que les échantillons sont dans le même ordre dans la matrice de comptage et l’annotation des échantillons, et de même pour les gènes dans la matrice de comptage et l’annotation des gènes.
R
stopifnot(rownames(count_matrix) == gene_metadata$gene)
stopifnot(colnames(count_matrix) == sample_metadata$sample)
R
se <- SummarizedExperiment(assays = list(counts = count_matrix),
colData = sample_metadata,
rowData = gene_metadata)
se
OUTPUT
class: SummarizedExperiment
dim: 1474 22
metadata(0):
assays(1): counts
rownames(1474): Asl Apod ... Lmx1a Pbx1
rowData names(9): gene ENTREZID ... phenotype_description
hsapiens_homolog_associated_gene_name
colnames(22): GSM2545336 GSM2545337 ... GSM2545363 GSM2545380
colData names(9): sample organism ... tissue mouse
Sauvegarde des données
L’exportation de données vers une feuille de calcul, comme nous
l’avons fait dans un épisode précédent, présente plusieurs limites,
telles que celles décrites dans le premier chapitre : incohérences
possibles entre , et . comme séparateurs
décimaux, et absence de définition des types des variables. De plus,
l’exportation vers une feuille de calcul n’est pertinente que pour des
données rectangulaires, telles que les tableaux de données et les
matrices.
Une méthode plus générale de sauvegarde des données, spécifique à R
et garantie sur tout système d’exploitation, consiste à utiliser la
fonction saveRDS. La sauvegarde d’objets de ce type génère
une représentation binaire sur le disque (en utilisant ici l’extension
de fichier rds), laquelle peut être chargée à nouveau dans
R à l’aide de la fonction readRDS.
R
saveRDS(se, file = "data_output/se.rds")
rm(se)
se <- readRDS("data_output/se.rds")
head(se)
En conclusion, lorsqu’il s’agit de sauvegarder des données depuis R
qui seront à nouveau chargées dans R, la méthode préférée consiste à
utiliser saveRDS et readRDS. Si des données
tabulaires doivent être partagées avec quelqu’un qui n’utilise pas R,
l’exportation vers une feuille de calcul textuelle constitue une bonne
alternative.
À l’aide de cette structure de données, nous pouvons accéder à la
matrice d’expression avec la fonction assay :
R
head(assay(se))
OUTPUT
GSM2545336 GSM2545337 GSM2545338 GSM2545339 GSM2545340 GSM2545341
Asl 1170 361 400 586 626 988
Apod 36194 10347 9173 10620 13021 29594
Cyp2d22 4060 1616 1603 1901 2171 3349
Klk6 287 629 641 578 448 195
Fcrls 85 233 244 237 180 38
Slc2a4 782 231 248 265 313 786
GSM2545342 GSM2545343 GSM2545344 GSM2545345 GSM2545346 GSM2545347
Asl 836 535 586 597 938 1035
Apod 24959 13668 13230 15868 27769 34301
Cyp2d22 3122 2008 2254 2277 2985 3452
Klk6 186 1101 537 567 327 233
Fcrls 68 375 199 177 89 67
Slc2a4 528 249 266 357 654 693
GSM2545348 GSM2545349 GSM2545350 GSM2545351 GSM2545352 GSM2545353
Asl 494 481 666 937 803 541
Apod 11258 11812 15816 29242 20415 13682
Cyp2d22 1883 2014 2417 3678 2920 2216
Klk6 742 881 828 250 798 710
Fcrls 300 233 231 81 303 285
Slc2a4 271 304 349 715 513 320
GSM2545354 GSM2545362 GSM2545363 GSM2545380
Asl 473 748 576 1192
Apod 11088 15916 11166 38148
Cyp2d22 1821 2842 2011 4019
Klk6 894 501 598 259
Fcrls 248 179 184 68
Slc2a4 248 350 317 796
R
dim(assay(se))
OUTPUT
[1] 1474 22
Nous pouvons accéder aux métadonnées de l’échantillon à l’aide de la
fonction colData :
R
colData(se)
OUTPUT
DataFrame with 22 rows and 9 columns
sample organism age sex infection
<character> <character> <integer> <character> <character>
GSM2545336 GSM2545336 Mus musculus 8 Female InfluenzaA
GSM2545337 GSM2545337 Mus musculus 8 Female NonInfected
GSM2545338 GSM2545338 Mus musculus 8 Female NonInfected
GSM2545339 GSM2545339 Mus musculus 8 Female InfluenzaA
GSM2545340 GSM2545340 Mus musculus 8 Male InfluenzaA
... ... ... ... ... ...
GSM2545353 GSM2545353 Mus musculus 8 Female NonInfected
GSM2545354 GSM2545354 Mus musculus 8 Male NonInfected
GSM2545362 GSM2545362 Mus musculus 8 Female InfluenzaA
GSM2545363 GSM2545363 Mus musculus 8 Male InfluenzaA
GSM2545380 GSM2545380 Mus musculus 8 Female InfluenzaA
strain time tissue mouse
<character> <integer> <character> <integer>
GSM2545336 C57BL/6 8 Cerebellum 14
GSM2545337 C57BL/6 0 Cerebellum 9
GSM2545338 C57BL/6 0 Cerebellum 10
GSM2545339 C57BL/6 4 Cerebellum 15
GSM2545340 C57BL/6 4 Cerebellum 18
... ... ... ... ...
GSM2545353 C57BL/6 0 Cerebellum 4
GSM2545354 C57BL/6 0 Cerebellum 2
GSM2545362 C57BL/6 4 Cerebellum 20
GSM2545363 C57BL/6 4 Cerebellum 12
GSM2545380 C57BL/6 8 Cerebellum 19
R
dim(colData(se))
OUTPUT
[1] 22 9
Nous pouvons également accéder aux métadonnées des caractéristiques à
l’aide de la fonction rowData :
R
head(rowData(se))
OUTPUT
DataFrame with 6 rows and 9 columns
gene ENTREZID product ensembl_gene_id
<character> <integer> <character> <character>
Asl Asl 109900 argininosuccinate ly.. ENSMUSG00000025533
Apod Apod 11815 apolipoprotein D, tr.. ENSMUSG00000022548
Cyp2d22 Cyp2d22 56448 cytochrome P450, fam.. ENSMUSG00000061740
Klk6 Klk6 19144 kallikrein related-p.. ENSMUSG00000050063
Fcrls Fcrls 80891 Fc receptor-like S, .. ENSMUSG00000015852
Slc2a4 Slc2a4 20528 solute carrier famil.. ENSMUSG00000018566
external_synonym chromosome_name gene_biotype phenotype_description
<character> <character> <character> <character>
Asl 2510006M18Rik 5 protein_coding abnormal circulating..
Apod NA 16 protein_coding abnormal lipid homeo..
Cyp2d22 2D22 15 protein_coding abnormal skin morpho..
Klk6 Bssp 7 protein_coding abnormal cytokine le..
Fcrls 2810439C17Rik 3 protein_coding decreased CD8-positi..
Slc2a4 Glut-4 11 protein_coding abnormal circulating..
hsapiens_homolog_associated_gene_name
<character>
Asl ASL
Apod APOD
Cyp2d22 CYP2D6
Klk6 KLK6
Fcrls FCRL2
Slc2a4 SLC2A4
R
dim(rowData(se))
OUTPUT
[1] 1474 9
Sélection d’éléments dans un SummarizedExperiment
Comme pour les tableaux de données, on peut extraire un sous-ensemble d’un SummarizedExperiment à l’aide d’indices numériques, de chaînes de caractères ou de valeurs logiques.
Ci-dessous, nous créons une nouvelle instance de la classe SummarizedExperiment qui ne contient que les 5 premières caractéristiques pour les 3 premiers échantillons.
R
se1 <- se[1:5, 1:3]
se1
OUTPUT
class: SummarizedExperiment
dim: 5 3
metadata(0):
assays(1): counts
rownames(5): Asl Apod Cyp2d22 Klk6 Fcrls
rowData names(9): gene ENTREZID ... phenotype_description
hsapiens_homolog_associated_gene_name
colnames(3): GSM2545336 GSM2545337 GSM2545338
colData names(9): sample organism ... tissue mouse
R
colData(se1)
OUTPUT
DataFrame with 3 rows and 9 columns
sample organism age sex infection
<character> <character> <integer> <character> <character>
GSM2545336 GSM2545336 Mus musculus 8 Female InfluenzaA
GSM2545337 GSM2545337 Mus musculus 8 Female NonInfected
GSM2545338 GSM2545338 Mus musculus 8 Female NonInfected
strain time tissue mouse
<character> <integer> <character> <integer>
GSM2545336 C57BL/6 8 Cerebellum 14
GSM2545337 C57BL/6 0 Cerebellum 9
GSM2545338 C57BL/6 0 Cerebellum 10
R
rowData(se1)
OUTPUT
DataFrame with 5 rows and 9 columns
gene ENTREZID product ensembl_gene_id
<character> <integer> <character> <character>
Asl Asl 109900 argininosuccinate ly.. ENSMUSG00000025533
Apod Apod 11815 apolipoprotein D, tr.. ENSMUSG00000022548
Cyp2d22 Cyp2d22 56448 cytochrome P450, fam.. ENSMUSG00000061740
Klk6 Klk6 19144 kallikrein related-p.. ENSMUSG00000050063
Fcrls Fcrls 80891 Fc receptor-like S, .. ENSMUSG00000015852
external_synonym chromosome_name gene_biotype phenotype_description
<character> <character> <character> <character>
Asl 2510006M18Rik 5 protein_coding abnormal circulating..
Apod NA 16 protein_coding abnormal lipid homeo..
Cyp2d22 2D22 15 protein_coding abnormal skin morpho..
Klk6 Bssp 7 protein_coding abnormal cytokine le..
Fcrls 2810439C17Rik 3 protein_coding decreased CD8-positi..
hsapiens_homolog_associated_gene_name
<character>
Asl ASL
Apod APOD
Cyp2d22 CYP2D6
Klk6 KLK6
Fcrls FCRL2
Nous pouvons également utiliser la fonction colData()
pour effectuer un sous-ensemble sur des éléments des métadonnées des
échantillons, ou la fonction rowData() pour effectuer un
sous-ensemble sur des éléments des métadonnées des caractéristiques. Par
exemple, ici, nous ne conservons que les miRNAs et les échantillons non
infectés :
R
se1 <- se[rowData(se)$gene_biotype == "miRNA",
colData(se)$infection == "NonInfected"]
se1
OUTPUT
class: SummarizedExperiment
dim: 7 7
metadata(0):
assays(1): counts
rownames(7): Mir1901 Mir378a ... Mir128-1 Mir7682
rowData names(9): gene ENTREZID ... phenotype_description
hsapiens_homolog_associated_gene_name
colnames(7): GSM2545337 GSM2545338 ... GSM2545353 GSM2545354
colData names(9): sample organism ... tissue mouse
R
assay(se1)
OUTPUT
GSM2545337 GSM2545338 GSM2545343 GSM2545348 GSM2545349 GSM2545353
Mir1901 45 44 74 55 68 33
Mir378a 11 7 9 4 12 4
Mir133b 4 6 5 4 6 7
Mir30c-2 10 6 16 12 8 17
Mir149 1 2 0 0 0 0
Mir128-1 4 1 2 2 1 2
Mir7682 2 0 4 1 3 5
GSM2545354
Mir1901 60
Mir378a 8
Mir133b 3
Mir30c-2 15
Mir149 2
Mir128-1 1
Mir7682 5
R
colData(se1)
OUTPUT
DataFrame with 7 rows and 9 columns
sample organism age sex infection
<character> <character> <integer> <character> <character>
GSM2545337 GSM2545337 Mus musculus 8 Female NonInfected
GSM2545338 GSM2545338 Mus musculus 8 Female NonInfected
GSM2545343 GSM2545343 Mus musculus 8 Male NonInfected
GSM2545348 GSM2545348 Mus musculus 8 Female NonInfected
GSM2545349 GSM2545349 Mus musculus 8 Male NonInfected
GSM2545353 GSM2545353 Mus musculus 8 Female NonInfected
GSM2545354 GSM2545354 Mus musculus 8 Male NonInfected
strain time tissue mouse
<character> <integer> <character> <integer>
GSM2545337 C57BL/6 0 Cerebellum 9
GSM2545338 C57BL/6 0 Cerebellum 10
GSM2545343 C57BL/6 0 Cerebellum 11
GSM2545348 C57BL/6 0 Cerebellum 8
GSM2545349 C57BL/6 0 Cerebellum 7
GSM2545353 C57BL/6 0 Cerebellum 4
GSM2545354 C57BL/6 0 Cerebellum 2
R
rowData(se1)
OUTPUT
DataFrame with 7 rows and 9 columns
gene ENTREZID product ensembl_gene_id
<character> <integer> <character> <character>
Mir1901 Mir1901 100316686 microRNA 1901 ENSMUSG00000084565
Mir378a Mir378a 723889 microRNA 378a ENSMUSG00000105200
Mir133b Mir133b 723817 microRNA 133b ENSMUSG00000065480
Mir30c-2 Mir30c-2 723964 microRNA 30c-2 ENSMUSG00000065567
Mir149 Mir149 387167 microRNA 149 ENSMUSG00000065470
Mir128-1 Mir128-1 387147 microRNA 128-1 ENSMUSG00000065520
Mir7682 Mir7682 102466847 microRNA 7682 ENSMUSG00000106406
external_synonym chromosome_name gene_biotype phenotype_description
<character> <character> <character> <character>
Mir1901 Mirn1901 18 miRNA NA
Mir378a Mirn378 18 miRNA abnormal mitochondri..
Mir133b mir 133b 1 miRNA no abnormal phenotyp..
Mir30c-2 mir 30c-2 1 miRNA NA
Mir149 Mirn149 1 miRNA increased circulatin..
Mir128-1 Mirn128 1 miRNA no abnormal phenotyp..
Mir7682 mmu-mir-7682 1 miRNA NA
hsapiens_homolog_associated_gene_name
<character>
Mir1901 NA
Mir378a MIR378A
Mir133b MIR133B
Mir30c-2 MIR30C2
Mir149 NA
Mir128-1 MIR128-1
Mir7682 NA
Défi
Extrayez les niveaux d’expression génique des trois premiers gènes dans les échantillons au temps 0 et au temps 8.
R
assay(se)[1:3, colData(se)$time != 4]
OUTPUT
GSM2545336 GSM2545337 GSM2545338 GSM2545341 GSM2545342 GSM2545343
Asl 1170 361 400 988 836 535
Apod 36194 10347 9173 29594 24959 13668
Cyp2d22 4060 1616 1603 3349 3122 2008
GSM2545346 GSM2545347 GSM2545348 GSM2545349 GSM2545351 GSM2545353
Asl 938 1035 494 481 937 541
Apod 27769 34301 11258 11812 29242 13682
Cyp2d22 2985 3452 1883 2014 3678 2216
GSM2545354 GSM2545380
Asl 473 1192
Apod 11088 38148
Cyp2d22 1821 4019
R
# Equivalent to
assay(se)[1:3, colData(se)$time == 0 | colData(se)$time == 8]
OUTPUT
GSM2545336 GSM2545337 GSM2545338 GSM2545341 GSM2545342 GSM2545343
Asl 1170 361 400 988 836 535
Apod 36194 10347 9173 29594 24959 13668
Cyp2d22 4060 1616 1603 3349 3122 2008
GSM2545346 GSM2545347 GSM2545348 GSM2545349 GSM2545351 GSM2545353
Asl 938 1035 494 481 937 541
Apod 27769 34301 11258 11812 29242 13682
Cyp2d22 2985 3452 1883 2014 3678 2216
GSM2545354 GSM2545380
Asl 473 1192
Apod 11088 38148
Cyp2d22 1821 4019
Défi
Vérifiez que vous obtenez les mêmes valeurs en utilisant le tableau
rna au format long.
R
rna |>
filter(gene %in% c("Asl", "Apod", "Cyd2d22")) |>
filter(time != 4) |>
select(expression)
OUTPUT
# A tibble: 28 × 1
expression
<dbl>
1 1170
2 36194
3 361
4 10347
5 400
6 9173
7 988
8 29594
9 836
10 24959
# ℹ 18 more rows
Le tableau au format long et le SummarizedExperiment
contiennent les mêmes informations, mais sont structurés différemment.
Chaque approche présente ses propres avantages : le premier convient
bien aux packages tidyverse, tandis que le second constitue
la structure privilégiée pour de nombreuses étapes de traitement
bioinformatique et statistique. C’est le cas, par exemple, d’une analyse
RNA-Seq classique avec le package DESeq2.
Ajout de variables aux métadonnées
Nous pouvons également ajouter des informations aux métadonnées. Supposons que vous souhaitiez ajouter le centre où les échantillons ont été collectés…
R
colData(se)$center <- rep("University of Illinois", nrow(colData(se)))
colData(se)
OUTPUT
DataFrame with 22 rows and 10 columns
sample organism age sex infection
<character> <character> <integer> <character> <character>
GSM2545336 GSM2545336 Mus musculus 8 Female InfluenzaA
GSM2545337 GSM2545337 Mus musculus 8 Female NonInfected
GSM2545338 GSM2545338 Mus musculus 8 Female NonInfected
GSM2545339 GSM2545339 Mus musculus 8 Female InfluenzaA
GSM2545340 GSM2545340 Mus musculus 8 Male InfluenzaA
... ... ... ... ... ...
GSM2545353 GSM2545353 Mus musculus 8 Female NonInfected
GSM2545354 GSM2545354 Mus musculus 8 Male NonInfected
GSM2545362 GSM2545362 Mus musculus 8 Female InfluenzaA
GSM2545363 GSM2545363 Mus musculus 8 Male InfluenzaA
GSM2545380 GSM2545380 Mus musculus 8 Female InfluenzaA
strain time tissue mouse center
<character> <integer> <character> <integer> <character>
GSM2545336 C57BL/6 8 Cerebellum 14 University of Illinois
GSM2545337 C57BL/6 0 Cerebellum 9 University of Illinois
GSM2545338 C57BL/6 0 Cerebellum 10 University of Illinois
GSM2545339 C57BL/6 4 Cerebellum 15 University of Illinois
GSM2545340 C57BL/6 4 Cerebellum 18 University of Illinois
... ... ... ... ... ...
GSM2545353 C57BL/6 0 Cerebellum 4 University of Illinois
GSM2545354 C57BL/6 0 Cerebellum 2 University of Illinois
GSM2545362 C57BL/6 4 Cerebellum 20 University of Illinois
GSM2545363 C57BL/6 4 Cerebellum 12 University of Illinois
GSM2545380 C57BL/6 8 Cerebellum 19 University of Illinois
Cela illustre que les slots de métadonnées peuvent s’étendre indéfiniment sans affecter les autres structures !
tidySummarizedExperiment
Vous vous demandez peut-être si nous pouvons utiliser des commandes
tidyverse pour interagir avec les objets
SummarizedExperiment. La réponse est oui, c’est possible
grâce au package tidySummarizedExperiment.
Rappelez-vous à quoi ressemble notre objet SummarizedExperiment :
R
se
OUTPUT
class: SummarizedExperiment
dim: 1474 22
metadata(0):
assays(1): counts
rownames(1474): Asl Apod ... Lmx1a Pbx1
rowData names(9): gene ENTREZID ... phenotype_description
hsapiens_homolog_associated_gene_name
colnames(22): GSM2545336 GSM2545337 ... GSM2545363 GSM2545380
colData names(10): sample organism ... mouse center
Chargez tidySummarizedExperiment, puis examinez à
nouveau l’objet se.
R
## BiocManager::install("tidySummarizedExperiment")
library("tidySummarizedExperiment")
se
OUTPUT
class: SummarizedExperiment
dim: 1474 22
metadata(0):
assays(1): counts
rownames(1474): Asl Apod ... Lmx1a Pbx1
rowData names(9): gene ENTREZID ... phenotype_description
hsapiens_homolog_associated_gene_name
colnames(22): GSM2545336 GSM2545337 ... GSM2545363 GSM2545380
colData names(10): sample organism ... mouse center
Il s’agit toujours d’un objet SummarizedExperiment, qui
conserve donc sa structure efficace, mais nous pouvons désormais le
consulter comme un tibble. La première ligne de la sortie indique qu’il
s’agit d’une abstraction
SummarizedExperiment-tibble. La deuxième ligne
indique également le nombre de transcrits et d’échantillons.
Nous pouvons désormais utiliser les commandes de tidyverse pour
interagir avec l’objet SummarizedExperiment.
Nous pouvons utiliser filter pour filtrer des lignes
selon une condition, par exemple pour afficher toutes les lignes d’un
échantillon.
R
se |> filter(sample == "GSM2545336")
OUTPUT
class: SummarizedExperiment
dim: 1474 1
metadata(1): latest_filter_scope_report
assays(1): counts
rownames(1474): Asl Apod ... Lmx1a Pbx1
rowData names(9): gene ENTREZID ... phenotype_description
hsapiens_homolog_associated_gene_name
colnames(1): GSM2545336
colData names(10): sample organism ... mouse center
R
se |> filter(sex == "Female")
OUTPUT
class: SummarizedExperiment
dim: 1474 12
metadata(1): latest_filter_scope_report
assays(1): counts
rownames(1474): Asl Apod ... Lmx1a Pbx1
rowData names(9): gene ENTREZID ... phenotype_description
hsapiens_homolog_associated_gene_name
colnames(12): GSM2545336 GSM2545337 ... GSM2545362 GSM2545380
colData names(10): sample organism ... mouse center
Nous pouvons utiliser select pour spécifier les colonnes
que nous souhaitons consulter.
R
se |> select(sample, sex)
WARNING
Warning: `when()` was deprecated in purrr 1.0.0.
ℹ Please use `if` instead.
ℹ The deprecated feature was likely used in the tidySummarizedExperiment
package.
Please report the issue at
<https://github.com/stemangiola/tidySummarizedExperiment/issues>.
This warning is displayed once per session.
Call `lifecycle::last_lifecycle_warnings()` to see where this warning was
generated.
OUTPUT
tidySummarizedExperiment says: Key columns are missing. A data frame is returned for independent data analysis.
OUTPUT
# A tibble: 32,428 × 2
sample sex
<chr> <chr>
1 GSM2545336 Female
2 GSM2545336 Female
3 GSM2545336 Female
4 GSM2545336 Female
5 GSM2545336 Female
6 GSM2545336 Female
7 GSM2545336 Female
8 GSM2545336 Female
9 GSM2545336 Female
10 GSM2545336 Female
# ℹ 32,418 more rows
Nous pouvons utiliser mutate pour ajouter des
informations métadonnées.
R
se |> mutate(center = "Heidelberg University")
OUTPUT
class: SummarizedExperiment
dim: 1474 22
metadata(1): latest_mutate_scope_report
assays(1): counts
rownames(1474): Asl Apod ... Lmx1a Pbx1
rowData names(9): gene ENTREZID ... phenotype_description
hsapiens_homolog_associated_gene_name
colnames(22): GSM2545336 GSM2545337 ... GSM2545363 GSM2545380
colData names(10): sample organism ... mouse center
Nous pouvons également combiner des commandes à l’aide du pipe
tidyverse |>. Par exemple, nous pourrions combiner
group_by et summarise pour obtenir la somme
des comptages pour chaque échantillon.
R
se |>
group_by(.sample) |>
summarise(total_counts=sum(counts))
OUTPUT
tidySummarizedExperiment says: A data frame is returned for independent data analysis.
OUTPUT
# A tibble: 22 × 2
.sample total_counts
<chr> <int>
1 GSM2545336 3039671
2 GSM2545337 2602360
3 GSM2545338 2458618
4 GSM2545339 2500082
5 GSM2545340 2479024
6 GSM2545341 2413723
7 GSM2545342 2349728
8 GSM2545343 3105652
9 GSM2545344 2524137
10 GSM2545345 2506038
# ℹ 12 more rows
Nous pouvons traiter l’objet tidy SummarizedExperiment comme un tibble ordinaire pour créer des graphiques.
Ici, nous représentons la distribution des comptages par échantillon.
R
se |>
ggplot(aes(counts + 1, group=.sample, color=infection)) +
geom_density() +
scale_x_log10() +
theme_bw()

Pour plus d’informations sur tidySummarizedExperiment,
consultez le site web
du package.
Message clé
SummarizedExperimentreprésente un moyen efficace de stocker et de manipuler des données omiques.Ils sont utilisés dans de nombreux packages Bioconductor.
Si vous suivez la formation suivante consacrée à l’analyse du
séquençage de l’ARN, vous apprendrez à utiliser le package Bioconductor
DESeq2 pour réaliser des analyses d’expression
différentielle. L’intégralité de l’analyse du package
DESeq2 est gérée dans un
SummarizedExperiment.
- Bioconductor est un projet qui fournit un support et des packages pour la compréhension de données biologiques à haut débit.
- Un
SummarizedExperimentest un type d’objet utile pour stocker et gérer des données omiques à haut débit.
Le projet Bioconductor a été lancé par Robert Gentleman, l’un des deux créateurs du langage R. Bioconductor propose des outils dédiés à l’analyse de données omiques. Il utilise le langage de programmation statistique R ; son code source est ouvert et son développement est ouvert à la communauté.↩︎