TD0 : Prise en main de R et Rstudio

Beaucoup d’informations complémentaires à ce premier TD sont disponibles sur ce guide en ligne : “Introduction to R and RStudio”, n’hésitez pas à le consulter (nous y ferons d’ailleurs référence ponctuellement tout au long de ce TD).

Installation de R et Rstudio

Toutes les informations sont sur le site de Rstudio. Voir en particulier la page des téléchargements

Windows

A priori, pas de soucis particuliers

Mac

A priori, pas de soucis particuliers

Ubuntu

Attention ! Il y a un conflit entre Ubuntu 20.04 et la version du .deb mise en ligne sur le site de Rstudio. Cependant, ces lignes de code semblent fonctionner :

  1. D’abord installer R sur le système en suivant par exemple ce site ou en copie-collant ces lignes dans un terminal :

sudo apt update -qq

sudo apt install --no-install-recommends software-properties-common dirmngr

wget -qO- https://cloud.r-project.org/bin/linux/ubuntu/marutter_pubkey.asc | sudo tee -a /etc/apt/trusted.gpg.d/cran_ubuntu_key.asc

sudo add-apt-repository "deb https://cloud.r-project.org/bin/linux/ubuntu $(lsb_release -cs)-cran40/"

  1. Installer le paquet libclang-dev et d’autres paquets qui peuvent être nécessaires selon votre système (en particulier pour l’utilisation de librairies additionnelles telles que tidyverse):

sudo apt install libclang-dev

sudo apt-get install -y libxml2-dev libcurl4-openssl-dev libssl-dev

  1. Installer Rstudio en utilisant gdebi :

sudo apt install gdebi-core

wget https://download1.rstudio.org/desktop/bionic/amd64/rstudio-1.4.1717-amd64.deb

sudo gdebi rstudio-1.4.1717-amd64.deb

Prise en main de R et Rstudio

Télécharger le fichier TD1.Rmd sur le portail, et l’ouvrir avec Rstudio

C’est la “source” de ce document. Vous pouvez donc ensuite défiler dans le fichier et arriver à cette exacte ligne!

Zones executables

Ce document est constitué de zones de textes, comme celles-ci, et de zones de code R (“chunks”) exécutables (indépendamment ou non).

Par exemple la zone suivante, crée un vecteur x, un vecteur y (défini comme le carré de x), et trace le graphique y(x).

x <- seq(0,1,length=100)
y <- x^2
plot(x,y)

Vous pouvez créer un nouveau “chunk” avec le raccourci Ctrl + Alt + i

Plus d’informations sur Rstudio ici

R comme calculatrice

R est avant tout une calculatrice très puissante. Il est donc possible de l’utiliser tel quel (voir fonctions de bases Ici)

1. Jouez avec ces fonctionnalités. Combien vaut 3 + 5 * 2^2 ? Vérifier aussi par exemple la valeur numérique de la racine carrée de 2. Indication (square root en anglais)

Variables et fonctions

Vous pouvez stocker des variables (et leur assigner une valeur) avec le signe <-

a <- 1
v1 <- 1:5
v2 <- seq(1,5,length=10)
v3 <- c(1,3,4,5,12.5)

Les variables ainsi créées apparaissent dans la fenêtre “environment” en haut à droite de Rstudio.

Plus d’informations sur les variables ici

2. Définir un vecteur v4 qui contient les valeurs 1,2 et 5

On peut définir des fonctions (qui peuvent être vues comme un type particulier de variables)

ecart_relatif_moyenne_mediane <- function(x) {
  moyenne = mean(x)
  mediane = median(x)
  abs((moyenne-mediane)/moyenne)
}

La fonction renverra comme résultat la dernière ligne. Cette fonction prend donc en entrée, un vecteur, elle calcule sa moyenne, sa médiane, et renvoie l’écart relatif entre les deux.

On peut ensuite évaluer cette fonction pour le vecteur v2 précédemment défini :

ecart_relatif_moyenne_mediane(v2)
[1] 0

3. Est ce que le résultat est logique ? Quelle est la sortie attendue, si on applique la fonction ecart_relatif_moyenne_mediane() au vecteur v4 que vous avez créé ? Vérifiez ensuite la valeur que la fonction retourne.

ATTENTION : les noms de variables peuvent contenir des lettres, des chiffres des points “.” ou tirets du bas (underscore) “_” MAIS ils ne peuvent pas commencer par un chiffre ou un “underscore”, NI contenir le moindre espace.

Vecteurs

Nous avons déja rencontré dans les lignes de codes précédentes, plusieurs façons de créer un vecteur :

Soit en explicitant la “collection” de valeurs

c(1,3,4,5,12.5)
[1]  1.0  3.0  4.0  5.0 12.5

Soit en définissant une “sequence”

seq(0,1,length=20)
 [1] 0.00000000 0.05263158 0.10526316 0.15789474 0.21052632 0.26315789
 [7] 0.31578947 0.36842105 0.42105263 0.47368421 0.52631579 0.57894737
[13] 0.63157895 0.68421053 0.73684211 0.78947368 0.84210526 0.89473684
[19] 0.94736842 1.00000000

ici : aller de 0 à 1 pour une longueur totale de 20 valeurs.

Soit à partir d’un autre vecteur

x <- seq(0,1,length=100)
y <- x^2

y est défini comme la carré de x. C’est à dire que chaque composante de y est définie comme la composante de x associée prise au carré.

voir plus de détails sur les vecteurs ici, en particulier la possibilité de manipuler des vecteurs “nommés”

4. Quels sont les noms de variable valides parmi la liste suivante :

min_height

max.height

_age

.mass

MaxLength

min-length

2widths

celsius2kelvin

5. Réutiliser les lignes de code précédentes pour tracer la courbe y = sin(x) entre 0 et 2 \(\pi\)

6. Construire une fonction qui “simule” le gain net après n jeux de pile ou face. pile, je gagne 1 euro, face, je perds un euro. Mots-clefs indicatifs éventuels : runif, round, sum

Manipulation de données

Importation de données d’un fichier texte

On peut par exemple importer l’évolution de la température moyenne en France depuis le siècle dernier (https://climateknowledgeportal.worldbank.org). Télécharger le fichier “tas_timeseries_annual_cru_1901-2021_FRA.csv” sur le portail. (l’option skip =1, est pour ignorer la première ligne du fichier qui est un commentaire non informatif. Cela dépend donc du formatage du fichier csv!)

donnees = read.csv("tas_timeseries_annual_cru_1901-2021_FRA.csv",skip=1)

Les informations contenues dans le fichier texte CSV (un simple fichier texte ASCII) sont transformées en un objet R appelé data.frame :

class(donnees)
[1] "data.frame"

On peut afficher le début de cet objet (en regardant la “tête”)

head(donnees)
  date France Alsace Aquitaine Auvergne Basse.Normandie Bourgogne Bretagne
1 1901   9.70   8.25     11.70     8.10            9.84      9.45    10.64
2 1902   9.80   8.38     11.89     8.27            9.70      9.54    10.60
3 1903  10.07   8.70     12.04     8.49           10.12      9.83    10.84
4 1904  10.42   9.18     12.43     8.94           10.18     10.24    10.88
5 1905   9.84   8.52     11.77     8.23            9.87      9.62    10.68
6 1906  10.24   8.69     12.15     8.68           10.40     10.00    11.07
  Centre Champagne.Ardenne Corse Franche.Comte Haute.Normandie Ile.de.France
1  10.12              9.12 12.42          8.06            9.51          9.96
2  10.08              9.07 12.75          8.26            9.34          9.83
3  10.48              9.52 12.73          8.43            9.82         10.31
4  10.71              9.81 13.31          8.99            9.92         10.50
5  10.21              9.31 12.57          8.31            9.53         10.04
6  10.71              9.75 12.68          8.54           10.16         10.59
  Languedoc.Rousillon Limousin Lorraine Midi.Pyrenees Nord.Pas.de.Calais
1               10.64     9.19     8.37         10.16               9.25
2               10.97     9.31     8.39         10.41               8.94
3               10.99     9.56     8.80         10.51               9.66
4               11.57     9.94     9.14         10.96               9.64
5               10.81     9.32     8.62         10.26               9.30
6               11.15     9.73     8.97         10.64               9.91
  Pays.de.la.Loire Picardie Poitou.Charentes Provence.Alpes.Cote.d.Azur
1            10.74     9.36            11.04                       9.27
2            10.66     9.18            11.08                       9.64
3            11.06     9.72            11.40                       9.70
4            11.21     9.85            11.66                      10.36
5            10.77     9.43            11.12                       9.55
6            11.29    10.03            11.53                       9.78
  Rhone.Alpes Cayenne Saint.laurent.du.maroni Administrative.unit.not.available
1        7.70   26.30                   26.55                             24.52
2        8.05   26.38                   26.60                             24.19
3        8.14   26.37                   26.58                             24.28
4        8.76   25.95                   26.17                             23.84
5        7.97   26.16                   26.39                             24.14
6        8.25   25.93                   26.18                             24.00
  Administrative.unit.not.available.1 Arrondissement_du_vent
1                               24.59                  19.76
2                               24.84                  19.88
3                               24.66                  19.77
4                               24.61                  19.78
5                               24.81                  19.86
6                               24.64                  19.81
  Arrondissement_souse_le_vent Fort.de.France La.Trinite Le.Marin Saint.Pierre
1                        19.17          25.30      25.42    25.91        25.11
2                        19.30          25.05      25.17    25.69        24.84
3                        19.19          25.10      25.23    25.75        24.89
4                        19.20          24.76      24.89    25.44        24.55
5                        19.29          24.99      25.11    25.64        24.78
6                        19.22          24.92      25.04    25.57        24.71

7. Pour visualiser les données, on peut aussi utiliser la commande View() directement dans la console. Quel est l’effet produit?

On voit que chaque colonne a un nom. On peut ensuite manipuler cet objet R.

Par exemple, récupérer le vecteur des années de mesure qui est stocké dans la première colonne :

annees = donnees[,1]

On peut récupérer le vecteur des températures moyennes de la France de la même façon (car stockée dans la deuxième colonne) :

temperature = donnees[,2]

ou en utilisant directement le nom de cette colonne grâce à l’opérateur “$” :

temperature = donnees$France

8. De même, créer un vecteur temperature qui contient toutes les températures correspondantes d’une part à l’Alsace, et d’autre part, à la Corse.

Premiers tracés de graphiques

9. Tracer le graphique de l’évolution de la température en France depuis 1901

10. Tracer le graphique qui compare la température de l’Alsace à celle de la Corse

Représentation de données

Tidyverse et ggplot

Le paquet Tidyverse dispose de nombreuses fonctionnalités qui vont nous permettre d’afficher et de représenter les données de façons esthétiques et efficaces. Si ce n’est pas encore fait, vous pouvez installer le paquet dans la console avec la commande install.packages("tidyverse")

et ensuite le charger en mémoire

library("tidyverse")
── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──
✔ dplyr     1.1.3     ✔ readr     2.1.4
✔ forcats   1.0.0     ✔ stringr   1.5.0
✔ ggplot2   3.4.4     ✔ tibble    3.2.1
✔ lubridate 1.9.2     ✔ tidyr     1.3.0
✔ purrr     1.0.2     
── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
✖ dplyr::filter() masks stats::filter()
✖ dplyr::lag()    masks stats::lag()
ℹ Use the conflicted package (<http://conflicted.r-lib.org/>) to force all conflicts to become errors

“ggplot” est un sous paquet de tidyverse spécialement dédié à la représentation graphique.

Premier tracé avec ggplot

Nous allons réaliser notre premier tracé avec ggplot de la façon suivante :

ggplot() + geom_point(mapping = aes(x = annees, y = temperature))

Le premier terme définit un ggplot

Le second terme définit le type de tracé (geom_point pour une représentation point par point) accompagné de son “mapping”. aes est l’abréviation de “aesthetics”

Fonctions avancées

ggplot permet de manipuler directement une dataframe :

ggplot(data=donnees)+ geom_point(mapping = aes(x=date,y=Auvergne))

ggplot(data = donnees) + geom_point(mapping = aes(x=Alsace,y=Corse)) + geom_segment(aes(x = 8, y = 8, xend = 12, yend = 12))

Exercice pratique sur des données expérimentales réelles

En 2017, une équipe du RDP a mis au point un nouvel algorithme pour segmenter des images issues de microscopies confocales afin de mesurer précisément la tailles des cellules et des noyaux correspondants. Leurs travaux ont été publiés dans (A. Kiss et al, https://www.ncbi.nlm.nih.gov/pmc/articles/PMC5738845/). La figure ci-dessous, extraite de l’article, illustre le résultat de la segmentation d’un méristème de fleur. Les données brutes correspondantes sont dans le fichier “cell-nuclei.csv” sur le portail.

#Image du meristeme floral

11. Importer les données brutes dans une data frame que l’on nommera donnees_meristeme

En consultant le guide en ligne sur les fonctionnalités de ggplot ICI,

12. Tracer un graphique qui trace le volume (volume) d’une cellule en fonction du volume de son noyau (nuc_volume), avec un code couleur qui différenciera les différentes couches cellulaires (layer). Attention la couche cellulaire est un paramètre discret, donc il n’est pas souhaitable d’avoir un code couleur dégradé, mais plutôt un code couleur discret.

13. Il y a beaucoup d’information proche de l’origine. Une façon de comprendre ce qui s’y passe et de regarder le même graphique en échelle logarithmique. Vous pouvez rajouter des options au ggplot qui transforment les axes x (et similairement avec y) en échelle log : + scale_x_continuous(trans=‘log10’) . Tracer un graphique qui trace le volume (volume) d’une cellule en fonction du volume de son noyau (nuc_volume), cette fois si en échelle log/log. Commenter quant à des erreurs de segmentations éventuelles.

Pour y voir plus clair, on peut aussi séparer chaque couche en un “subplot”. C’est possible avec le mot-clef “facet” : Voir ici

14. Tracer à nouveau un graphique qui trace le volume (volume) d’une cellule en fonction du volume de son noyau, mais en utilisant un “subplot” pour chaque couche de cellule. Puisqu’il y a 4 couches, on pourra par exemple faire 4 “subplots” rangés en 2 lignes et 2 colonnes.

De manière générale, il est possible de composer différents éléments avec ggplot. Nous avons déja vu les points avec geom_point, mais il est aussi possible de tracer un “smooth”, avec geom_smooth, Voir ici.

ATTENTION, AVERTISSEMENT IMPORTANT : Ce smooth est un lissage qui ne doit être pris ici que comme un guide pour l’œil. Nous verrons plus tard dans la suite du cours comment faire des régressions dont on maîtrisera le sens.

15. Tracer, le volume des cellules en fonction de sa surface, en superposant les points expérimentaux, et une courbe “smoothée”, avec un code couleur qui dépendra de la couche cellulaire

Enregistrement de graphes

Pour enregistrer vos graphiques sous forme d’image (png) ou mieux, d’image vectorielle (pdf), vous pouvez utiliser la fonction “ggsave”. Voir ici tous les détails

16. Recréer les graphes des questions 9 et 11, et les sauvegarder au format pdf (graphe_Q9.pdf et graphe_Q11.pdf par exemple)

17. Recréer les graphes des questions 9 et 11, mettez les côte à côte dans un nouveau graphe, que vous allez sauvegarder au format pdf (graphe_combinaison.pdf). Voir pour cela le paquet “cowplot” à la même adresse que ci-dessus

18. Bonus : Rendre la figure “publishing quality”, en fusionnant les légendes, en explicitant les axes (en mettant les unités par exemple), en mettant un joli titre pour la légende

Reformatage de données, “facteurs” et “apply”

Reformatage de données

Nous verrons dans le TD 2, qu’il sera souvent utile de re-formater des données. Voici par exemple un bout de code qui à partir de notre dataframe expérimentale donnees_meristeme crée une nouvelle dataframe qui contient une colonne avec le Volume, et une autre colonne qui lui associe un “type” (cellule ou noyau).

donnees_meristeme <- read.csv("cell-nuclei.csv") # normalement vous avez déja chargé ces données à la question 11

n <-length(donnees_meristeme$nuc_volume)
donnees_volumes <- data.frame(V = c(donnees_meristeme$nuc_volume,donnees_meristeme$volume),
                   type = c(rep("noyau", n),
                             rep("cellule", n)))
head(donnees_volumes)
          V  type
1 0.1583869 noyau
2 0.2375804 noyau
3 0.1781853 noyau
4 0.1682861 noyau
5 0.1880845 noyau
6 0.1781853 noyau

Facteurs

On voit que la classe de la colonne “type” est un facteur

class(donnees_volumes$type)
[1] "character"

Vous pouvez lire cette page web à propos des facteurs

C’est un type d’objet R qui peut prendre différents niveaux de valeurs. Ici “cellule” ou “noyau”. Par exemple si on regarde la valeur du premier élément :

donnees_volumes$type[1]
[1] "noyau"

L’ordinateur nous renvoie la valeur et “noyau” et les niveaux possibles : “Levels: cellule noyau”

Si on revient à notre dataframe donnees_meristeme. On aimerait pouvoir traiter la couche cellulaire “layer” comme un facteur, car en effet il n’y a que 4 états possibles 1,2,3 ou 4. Si on affiche notre dataframe :

head(donnees_meristeme)
  label center_x  center_y  center_z   volume  surface    Dmax_x layer
1     2 44.22622 1.7339104 0.4498017 24.83705 42.87615 115.98674     1
2     3 58.55543 0.7778581 0.5192494 15.69020 30.08246 125.20524     2
3     4 64.98994 1.3738259 0.4607645 17.57105 32.61815  88.18728     2
4     5 72.68325 1.5645261 0.4008138 32.38022 54.80540 200.52085     3
5     6 79.99965 1.7433276 0.5680080 33.63742 54.86303 122.66675     3
6     7 91.33287 0.6202327 0.5241943 11.64144 24.14665  79.66666     3
  mean_curvature gaussian_curvature principal_curvature_min
1             NA                 NA                      NA
2             NA                 NA                      NA
3             NA                 NA                      NA
4             NA                 NA                      NA
5             NA                 NA                      NA
6             NA                 NA                      NA
  principal_curvature_max nuc_center_x nuc_center_y nuc_center_z nuc_volume
1                      NA     44.32564     2.012972    0.7380897  0.1583869
2                      NA     58.58195     1.109371    0.7515095  0.2375804
3                      NA     65.46483     1.562663    0.7634382  0.1781853
4                      NA     75.03728     1.907192    0.7578247  0.1682861
5                      NA     80.08944     1.740338    0.7571599  0.1880845
6                      NA     90.93265     1.013941    0.7395808  0.1781853
  nuc_surface    Dmax_y
1    2.650945  7.444211
2    3.111979  7.856999
3    2.823833  7.118120
4    2.420428  4.825164
5    2.535686  5.701131
6    3.630642 13.728462

On voit que layer est de type

class(donnees_meristeme$layer)
[1] "integer"

Il est possible de transformer cette colonne en objet de type facteur avec la simple commande :

donnees_meristeme$layer <- as.factor(donnees_meristeme$layer)

Et désormais :

class(donnees_meristeme$layer)
[1] "factor"

Nous reverrons l’utilité d’un tel procédé au TD2.

“apply”

simple fonction apply

La fonction apply permet d’appliquer une fonction sur toutes les lignes ou toutes les colonnes d’une data frame (ou une matrice). Si on souhaite appliquer la fonction sur les lignes, on va spécifier l’argument margin=1 (en pratique, on utilise que le 1 en second argument de la fonction). Si on veut faire l’opération sur les colonnes, on utilise margin=2.

19. Utiliser la fonction apply pour calculer la moyenne (fonction mean) des températures de toutes les régions de France.

variantes (sapply, tapply, …)

tapply

La fonction tapply permet d’appliquer une fonction sur une variable, par sous-groupe de données définies par des facteurs différents. Elle s’utilise avec la syntaxe tapply(variable, facteur, function)

20. Utiliser la fonction tapply pour calculer la moyenne des volumes en fonction du facteur (est ce un noyau ou une cellule)

sapply

Nous avons vu à la question 6 que nous pouvions construire une fonction gain_net qui permet de simuler le gain net d’une partie de n lancers de pile ou face.

gain_net <- function(n) {
nombres_entre_0_1 <- runif(n)
entiers_0_1 <- round(nombres_entre_0_1)  
entiers_plus_moins <- 2*entiers_0_1 -1
somme <- sum(entiers_plus_moins)
somme
}

Si nous voulons désormais créer un vecteur de taille m qui contiendra le résultat de m réalisations de ce type. Nous pouvons utiliser la fonction `sapply’ pour “appliquer” cette fonction à un autre vecteur précédemment défini.

nombre_de_lancers_par_partie <- 100  # n
nombre_de_parties <- 10000         #m
nombre_de_lancers_dans_les_parties <- rep(nombre_de_lancers_par_partie,nombre_de_parties)
realisations <- sapply(nombre_de_lancers_dans_les_parties,gain_net)
hist(realisations)