Académique Documents
Professionnel Documents
Culture Documents
{}
[]
Cours 1
Introduction au language - types de
variables et d'objets
Partie I : Premiers pas avec l'interface replit
Une fois connecté dans l'interface d'un cours, vous vous retrouvez dans l'espace d'un
ordinateur sous linux, plus précisément dans un dossier nommé d'après le nom du TP (ici, le
dossier s'apelle typesvariables). Chaque étudiant à un dossier qui lui est propre.
à gauche sont listés les fichiers présents dans le dossier (Files). Il est possible de
sélectionner les fichiers et passer de l'un à l'autre en cliquant dessus. Les icones au
dessus et sur la gauche permettent d'ajouter de nouveaux fichiers, ou encore d'interagir
avec les outils replit.
au centre un éditeur de texte permet de lire et modifier les fichiers, une fois
sélectionnés dans la partie gauche. C'est cette partie que vous utiliserez pour écrire vos
scripts.
à droite la partie "ordinateur" à proprement parler. Plusieurs onglets sont présents
(Console, Shell, Markdown).
1. L'onglet Markdown permet de visualiser les fichiers au format markdown (comme le fichier
README.md que vous êtes en train de lire en ce moment) mais interprétés de manière formattée,
plus lisible. Cet onglet peut-être supprimé en décochant l'option "Preview" en haut de cette fenêtre.
Il est demandé de suivre le cours depuis l'onglet markdown.
2. L'onglet Shell correspond au terminal linux pour votre session. Quand vous vous connectez à
n'importe quel ordinateur sous linux via le terminal (en ligne de commande), c'est exactement ce à
quoi ça ressemble. Il y a également des points communs avec le terminal Mac d'Apple. Certaines
commandes du shell Unix sont disponibles, mais de manière limitée dans replit.
3. L'onglet Console est spécifique à replit et il est proposé par commodité : lorsqu'un fichier
script est lancé avec le boutton "Run" (au dessus en vert) il permet de vérifier le résultat de
l'execution du script dans cet onglet (= la sortie produite). A noter qu'il reste possible d'executer un
script via le terminal (Shell).
Question 1 : cliquer sur le fichier "main.r". L'extension .r du fichier nous indique qu'il s'agit
d'un script R. Une fois le fichier script sélectionné, cliquer sur le bouton "Run" en haut (icone
verte). L'onglet console s'ouvre automatiquement et lance le script. A quoi sert la fonction
print() présente dans le script ?
Question 2 : modifier le script pour afficher le texte de votre choix et lancer le script.
Note : sous systèmes Unix, les fichier commencant par un "." comme le fichier .Rprofile sont
des fichiers cachés, mais replit les affiche dans le navigateur de fichiers. Ce sont souvent des
fichiers qui contiennent des historiques, des données de configuration ou des options pour le
système ou les programmes. Ici, le fichier .Rprofile contiens des réglages d'option qui sont
chargés au démarage de R. Il est possible de le modifier, d'y ajouter des fonctions personelle
ou différentes options, mais pour le moment ce fichier sera ignoré.
Le symbole > présent dans le terminal indique que l'interpréteur R attend une commande.
Pour quitter R et revenir au terminal, taper la fonction "q()" puis entrée.
q()
Note : cette commande vous est rapellée lorsque vous lancer R. Par ailleurs en quittant il est
proposé d'enregistrer une "image" de la session avant de quitter (contenant l'historique des
commandes, et toutes les variables enregistrées) qui seront automatiquement rechargées
lorsque R sera relancé. (y = yes ; n = no ; c = cancel).
Il est possible de préciser directement si l'on souhaite garder ou non l'historique en passant un
argument à la fonction q() :
q(save="yes")
Note : Il peut-être parfois intéressant de quitter et relancer R pour repartir avec une session
fraîche, supprimant toutes les variables en mémoire.
Note 2 : L'intépréteur permet de tester des commandes en live lorsque l'on écrit un script. La
manière classique de développer des scripts très complexes est d'avoir un fichier script ouvert
d'un côté, et un terminal de l'autre. Cela permet de tester des commandes en direct, puis
lorsque l'on est ceetain qu'elles fonctionnent de les copier dans le fichier script final. Dans
replit, écrire un fichier script et le tester avec le bouton "Run" reviens au même pour de petit
scripts. Il existe également des logiciels d'environnement de développement (des "IDE", eg.
Rstudio) qui permettent de reproduire cette façon de travailler sur ordinateur.
NOTE : Tout ce qui est tapé dans l'intepréteur sera évalué par R, à moins d'ajouter le symbole
dièse # devant. Cette particularité est très utile pour ajouter des commentaires au code, et sera
largemet utilisé dans cette unité d'enseignement. Il est recommendé d'ajouter des
commentaires avant de lancer les commandes ci-dessous pour prendre des notes sur ce qui est
fait. Les commentaires pouront être sauvegardés à la fin de ce TP.
1+2
Example 5 puissance 3
5^3
Une commande doit être complète pour être reconnue et executée. Mais une commande peut
également être écrite sur plusieurs lignes. Lorsque qu'une commande est incomplète, R
attends que l'on la complète dans les lignes suivantes pour pouvoir l'executer. Le symbole >
de l'interpréteur deviens alors un + (attente d'ajout d'autres lignes).
IMPORTANT : l'erreur classique consiste à taper des commandes incomplètes, qui laissent
l'intérpréteur en attente, sans donner de résultat. Le codeur inexpérimenté pourrait avoir
l'impression que le système est bloqué. Pour sortir d'une telle situation, il suffit alors de
compléter la commande.
Example : taper
16 /
Tapez alors :
2
Le résultat de 16 / 2 apparaît.
( ( 7 + 3 ) / (5 - 1)
ASTUCE 1 : lorsque des commandes très complexes sont tapées et que l'on ne retrouve plus
ce qui manque pour pouvoir terminer la commande, il est possible d'interompre la commande
avec CTRL+C (C = cancel , il n'est donc pas possible de faire de copier avec ce raccourcis
dans un terminal..). Cela peut arriver lorsque l'on oublie de refermer une parenthèse, ou des
guillemets imbriqués dans des commandes complexes.
ASTUCE 2 : Dans l'interpréteur, il est possible de naviguer dans l'historique des commandes
qui ont été tapée à l'aide des touches "haut" et "bas". C'est une astuce fondamentale.
Lorsqu'une commande tapée est erronée, il est ainsi très facile de la faire réapparaitre pour la
modifier facilement.
Assignation de variables
Valeurs numériques
On peut très facilement assigner des valeurs à des variables. Par exemple, pour donner la
valeur de 5 à x :
x=5
Cette manière (=) d'assigner une valeur à une variable fonctionne avec de nombreux autres
languages de programmation (languages interprétés et compilés). Mais la convention sous R
est d'utiliser une flèche pour assigner des valeurs. Cette convention sera maintenue pour
l'ensemble de ce cours.
x <- 5
Intérêt : Stocker des nombres entiers ou avec des décimales (même lorsque les décimales sont
nulles) ne prends pas la même place dans la mémoire d'un ordinateur... En pratique, R est
encore ici plutôt sympa car il converti automatiquement les types numériques en fonctions des
besoins des opérations. Les typages numeric/double/integer sont en pratique utilisés dans des
situations de code plus avancées.
class(x)
Et de modifier la classe de x :
as.integer(x)
TRES IMPORTANT : Lancer la fonction as.integer(x) ne permet que d'afficher le résultat de
la conversion. Si l'on veut réecrire x après l'avoir transformée en nombre entier, il faut
renvoyer le résultats vers x pour réecrire dessus.
as.integer(x)
class(x)
x <- as.integer(x)
class(x)
Changer le type de classe d'une variable peut toutefois entraîner une perte d'information. Par
exemple en transformant un décimal en entier...
as.integer(5.9)
as.integer(5.1)
Question : comment est arrondi un décimal lors de sa conversion en entier par R (défaut /
excès) ?
Il est possible d'utiliser n'importe quelle chaine de caractère pour définir une variable, et
également de passer directement le résultat d'une opération lors de l'écriture d'une variable :
x <- 1
y <- 7
masupervariable <- 19
monResultat <- x + y
monResultat
Une variable ne peux toutefois pas commencer par un nombre (eg. 7variable ne fonctionne
pas). Commencer par un point est également déconseillé, car cela est utilisé par convention
dans certaines situations.
log(0)
La déclaration de chaînes de caractères comme valeur d'une variable se fait par l'ajout de
guillemets.
L'ajout de guillemet permet également d'introduire des espaces dans une chaîne de caractères
(sans guillemets R interpréterait un espace comme une séparation entre les commande). Les
guillemets permettent donc de délimiter une séquence de caractère.
monprof <- "Jules GILET"
Des nombres peuvent également être déclarés et intéprétés comme une chaîne de caractères.
Les opérations mathématiques sur des chaînes de caractère ne sont naturellement pas
permises.
Par exemple :
x <- 5
x > 10
Les variables de type logiques permettent donc de stocker des tests de condition. Il permettent
de développer des fonctions qui réagissent à certaines conditions.
Sous R, les fonctions se présentent sous forme d'un nom puis de parenthèses.
Les commandes suivantes que l'on a deja utilisé sont des fonctions R :
q()
class()
as.integer()
Comme pour une opération mathématique simple, une fonction peut nécessiter des données en
entrée pour faire un calcul. Par exemple, lorsque l'on fait une simple opération d'addition, il
faut des valeurs à additionner :
Les parenthèses d'une fonction servent à recceuillir des données en entrée. Pour comprendre,
il existe une fonction pour calculer une somme sous R.
sum(1, 2)
La fonction sum() a recceuilli comme arguments les valeurs 1 et 2 et les a ajoutées.
Il est ainsi possible de passer différents arguments (pas forcément numériques) à une fonction
pour lui demander de s'executer dans un but précis. Par exemple lorsque nous avons avons
utlisé la fonction q(), nous avons précisé en argument l'option save pour indiquer si nous
souhaitions que la fonction quitte l'intepréteur en sauvegardant ou non l'environnement.
q(save='no')
Ces points seront rediscutés plus en détail dans la partie sur la programmation fonctionelle.
Pour le moment il est simplement important de comprendre comment s'écrit une fonction et
à quoi servent les parenthèses (recceuillir des arguments pour une fonction), puisque
l'utilisation de fonctions est le coeur de l'utilisation de R.
IMPORTANT : Pour chacune des fonctions disponibles dans R de base, il est possible
d'obtenir des informations sur le rôle de la fonction et la liste des arguments qu'il est possible
de lui passer, à l'aide de la fonction help(). On indiquera simplement le nom de la fonction
sans parenthèses.
Examples :
help(sum)
help(q)
Il est possible de naviguer avec les flèches haut et bas dans l'aide, et d'appuyer sur la touche q
(quit) pour sortir de l'aide.
Sortie graphique
Un intérêt majeur de R est de pouvoir faire des représentations graphiques simplement et
facilement, grâce à des fonctions dédiées. Les graphiques peuvent être écrits dans des fichiers,
mais R possède également une sortie graphique pour les afficher. Dans l'interface replit, cette
sortie apparaît au dessus du terminal (un petit trait permet de redimensionner la taille du
terminal et de la sortie graphique).
Example : soit 5 valeurs de x (de 1 à 5) et 5 valeurs de y (de 6 à 10). On peut représenter
facilement y en fonction de x avec :
plot(x=1:5, y=6:10)
La représentation et visualisation de données sera discuté plus en détail dans cette unité
d'enseignement.
savehistory(file="premierTP.rhistory")
Vous pouvez enregistrer le fichier comme bon vous semble (l'essentiel est de vous y
retrouver), puis ouvrir le fichier avec l'éditeur de texte en cliquant dessus dans la liste des
fichiers à gauche. Vous pouvez corriger des fautes de frappes si vous en avez fait pendant le
TP.
Il est également possible d'afficher l'historique directement dans l'interpréteur pour revoir les
commandes qui ont été entrées.
history()
Utilisation : comme pour l'aide, naviguer avec les flèches haut et bas et sortir avec la touche q.
Points clés
Voilà qui termine ce premier TP. Nous avons vu :
Cours 2
Stocker de l'information : structure des
données
Dans le précédent TP, nous avons vu que l'on peut attribuer des valeurs a des objets. En
pratique, l'analyse de données de Santé nécessite de manipuler des quantités bien plus
volumineuses que de simples variables scalaires (eg. valeurs uniques). Vous avez
certainement été amené à traiter des données présentes sous forme de table. Sous R ces tables
correspondent à des dataframes. Mais il existe d'autres formats de stockage des données qui
sont très pratiques et utilisés en routine pour effectuer un traitement d'informations
complexes. Nous commencerons par la format de stockage le plus simple : les vecteurs.
Le stockage de données sous R suit des règles très précises, issues des mathématiques, qu'il
est important de bien comprendre pour éviter par la suite de se retrouver avec des erreurs
impossible à interpréter. Ces contraintes peuvent paraîître un peu rigide au codeur débutant,
mais elles sont indispensables au développement informatique, et nécessaire pour traiter des
information avec robustesse. Il est important que vous essayez les commandes de cette partie
TD dans l'interpréteur, pour bien comprendre les commandes, la structure des objets et la
manière de visualiser les données qu'ils contiennent.
Vecteurs
Un vecteur est une suite de valeurs. Pour visualiser plus facilement, en reprenant l'exemple
d'un tableau de données, un vecteur peut correspondre à une ligne ou une colonne d'un
tableau. Lorsque l'on assigne une valeur unique à une variable, sous R on créé en fait un
vecteur avec une seule valeur.
1:10
24:27
La fonction seq() est également très pratique pour générer une séquence de nombre : une suite
incrémentielle de numerics entre deux valeurs.
# suite entre 1 et 10 de 2 en 2
seq(from = 1, to = 10, by = 2)
# suite entre 5 et 7 de 0.5 en 0.5
seq(from = 5, to = 7, by = 0.5)
La fonction c() permet de concaténer une suite de valeurs séparées par des virgules, qui est
très pratique pour créer des vecteurs numériques plus personalisés.
Même si il est possible de mélanger différent type de valeurs par concaténation, la création
d'un vecteur implique que toutes les valeurs d'un vecteur doivent nécessairement être de
même type.
Question : de quel classe sera un vecteur créé avec les valeurs 1, 2, 7, "intrus", 12 ? Pour
quelle raison ?
Solution :
Indices de vecteurs
Un vecteur étant une suite de valeurs, il est très facile de retrouver un élement au sein d'un
vecteur en cherchant sa position dans le vecteur. On parle d'index ou d'indice d'un vecteur.
Les index sont indiqués entre crochet à la fin du nom d'un vecteur. Cette syntaxe est par
ailleurs la même pour une matrice ou un dataframe, ce sera discuté plus loin.
Il est souvent utile de connaitre la longueur d'un vecteur sans avoir à compter à la main tous
ses éléments. C'est possible grâce à la fonction :
length(vec)
Question : comment afficher le dernier élément d'un vecteur sans en connaitre la longueur ?
Solution :
vec[ length(vec) ]
# ou encore l'avant dernier élément
vec[ length(vec) - 1 ]
Note : sous R le premier élément est toujours 1 (contrairement à d'autres languages comme
pyton ou les index commencent à 0...)
Plutôt que de chercher des valeurs d'après leur position dans le vecteur, il peut-être pratique
de les chercher plus simplement par des noms. R permet d'ajouter des étiquettes de nom à
chacune des positions d'un vecteur. Les noms sont accessibles via la fonction name().
# on peut afficher la liste des noms d'une vecteur une fois définie
names(notes)
# ou encore afficher une partie de ce vecteur de nom à l'aide d'index..
names(notes)[ c(2, 4) ]
# lorqu'un vecteur est créé, il n'a naturellement pas de noms
Les données deviennent plus lisibles. Le vecteur avec des noms commence à ressembler à une
petite table, mais il n'y a encore qu'une seule dimension de données numeric dans le vecteur.
Les noms ne sont qu'un label associé au vecteur.
IMPORTANT : Les valeurs booléenes doivent être écrites en anglais (comme tout code R), et
surtout en CAPITALES pour êêtre reconnues comme telle (attention pour les utilisateurs de
python...) : TRUE / FALSE.
Les valeurs booléenes sont binaires, et s'opposent. L'inverse de TRUE et FALSE, l'inverse de
FALSE est TRUE. Il exixte un opérateur logique permettant de trouver l'inverse d'une
variable booléenne : !.
girls
!girls
Il est également possible de faire une recherche logique dans un vecteur. Par exemple, quel
nom de vecteur est égal à marc ?
names(notes) == "marc"
Le résultat est un vecteur indiquant pour chacune des position si la condition est vraie ou
fausse (chacun des noms est comparé à "marc"). On peut alors facilement réutiliser ce résultat
pour afficher l'élément du vecteur qui nous intéresse.
Il est également possible de réaliser des tests sur des valeurs numériques (sur les valeurs
numeric du vecteur cette fois, pas sur les noms qui sont de classe character...)
R ayant été développé initialement pour et par les statisticiens, il existe de très nombreuses
fonctions qui permettent de réaliser des calculs descriptifs facilement de cette manière.
# maximum
max(notes)
# minimum
min(notes)
# médianne
median(notes)
# quantiles
quantile(notes, probs=0.25)
quantile(notes, probs=0.75)
# BONUS :
summary(notes)
# Bonus 2 : visualisation
boxplot(notes[ girls ], notes[ !girls ], names = c("girls", "boys"))
Question : Calculer la différence entre la moyenne des notes des filles et des garçons
Vérifier les données
Contrairement à un tableur, lorsque l'on manipule des données sous R, elles ne sont pas
toujours visibles et présentes sous nos yeux. Il est toujours possible d'afficher le contenu d'une
variable, mais lorsque les données sont volumineuses, ce n'est pas toujours très pratique. Deux
commandes sont particulèrement utiles pour jeter rapidement un oeuil au début ou à la fin des
données, les fonctions head() et tail().
Ces commandes sont également utilisables pour inspecter des matrices ou dataframes, nous y
reviendront.
Pour aller plus loin : Ces commandes existent également sous terminal linux et Mac OS.
Matrices
Une matrice s'apparente à un tableau. Toutefois, il s'agîît d'un objet mathématique précis :
comme pour les vecteur, les données d'une matrice doivent nécessairement être de la même
classe.
La fonction matrix() permet de créer facilement des matrices. On passera alors au minimum
en argument les valeurs de la matrice, le nombre de lignes et de colonnes.
On peut voir qu'R a créé une matrice et l'a remplie d'une suite de chiffres, en commençant
par les lignes, une colonne à la fois.
La matrice contiens des index de lignes et de colonnes, affichés sur le côté et en haut, qui sont
indiqués entre [] tout comme pour les vecteurs.
La matrice ayant deux dimensions, il faut pouvoir établir un indice de ligne et de colonne. Ces
indices sont séparés par une virgule entre les crochets, sous la forme :
Pour afficher des éléments dans une matrice à l'aide des indices, la procédure est la mêême
que pour les vecteurs, mais dans deux dimensions :
Il est ainsi possible d'extraire une ligne ou une colonne d'une matrice, en n'indiquant que
l'indice qui nous intéresse, ce qui créera alors un vecteur. Note : c'est cette information qui est
indiquée à la place des noms de ligne et colonne d'une matrice qui viens d'être initialisée.
IMPORTANT : à bien retenir, pour des données à deux dimensions (matrices et dataframe),
le premier indice est toujours la rangée, le second indice la colonne.
NOTE : vous comprenez maintenant mieux pourquoi il est important de concaténer avec c()
une suite d'index pour sélectionner plusieurs éléments d'un vecteur. En passant simplement
une suite d'index entre [], R va chercher à trouver des index dans un élément à plusieurs
dimensions, alors qu'un vecteur n'en a qu'une seule. C'est un bon exemple illustratif de
l'importance de respecter la syntaxe d'un language de programmation. Des erreurs de syntaxe
menant à des interprétations différentes par le langage de l'intention de départ...
Il est enfin possible d'extraire une sous matrice en sélectionnant plusieurs lignes et colonnes.
# lignes 2 à 4, colonnes 2 et 3
sousmat <- mat[ c(2:4), c(2, 3) ]
sousmat
Notez que l'on produit une sous-matrice différente de la première, les noms de lignes et de
colonnes sont donc réinitialisés. Comme pour les vecteurs, il est possible de modifier les
noms des lignes et colonnes. Comme une matrice a deux dimension, la fonction name() seule
n'est pas suffisante.
Des fonctions existent également pour réaliser des calculs statistiques facilement.
# moyennes...
colMeans(mat)
On peut également réaliser des filtres par test logique tout comme pour les vecteurs.
Dataframes
Les dataframes sont probablement le type d'objet le plus courement utilisé pour l'analyse de
données de Santé. Ils permettent de mélanger des données numeric et character, regroupés par
colonnes. Ce format est particulièrement pratique pour stocker des données complexes.
Les dataframes sont créés avec la fonction data.frame(), on passe en argument chacune des
colonnes avec son nom.
df <- data.frame(nom = c("marie", "paul", "alice", "jean"), age = c(19, 20, 19, 18), note = c(14, 15, 17, 11))
df
rownames(df)
colnames(df)
La fonction str() permet de visualiser la structure d'un dataframe, qui reprend une description
du tableau et la classe de donnée présente. Remarquez le symbole $ pour chacune des
colonnes.
str(df)
df
Chaque ligne de donnée a été numérotée de manière unique. Il est toujours possible de
modifier le nom des colonnes et des lignes avec colnames() et rownames(), mais il
est impératif que les nouveaux noms des lignes soient uniques.
Les données du dataframe n'étant pas de la même classe, il n'est pas possible de réaliser
d'opération mathématique ni de test d'égalité globale :
df + 1
df > 10
# non valide
Certaines fonctions peuvent autodétecter le format de l'objet R et s'adaptent très bien aux
dataframes. Essayez le fonction summary(df)...
df[ , 1 ]
# ou de manière plus explicite
df[ , "age" ]
Les colonnes d'un dataframe ayant toutes un nom unique, il est également possible d'extraire
une colonne à l'aide du symbole $, que nous avons vu avec la fonction str()
PRO TIP : Il est possible d'utiliser l'autocomplétion pour afficher les noms de colonnes. En
appuyant sur la touche tabulation (à gauche de la touche A) deux fois de suite, R va essayer de
devinner et compléter une commande à partir de ce qui a déjà été tapé. Essayez de taper "df$"
puis tabulation deux fois. Puis a et tabulation. R est également capable d'afficher les options
de toutes les fonctions, taper une fonction, et avec le curseur entre les parenthèses deux fois la
touche tab...
# dimensions
dim(mat)
dim(df)
# nombre de colonne
ncol(mat)
ncol(df)
# notez que le nom est le même (nrow, ncol) que lors de la création de la matrice
length(mat)
# renvoie le nombre d'éléments dans la matrice (nombre de valeurs)
length(df)
# renvoie le nombre de colonne dans le dataframe...
length(df) == ncol(df)
Listes
Les listes permettent de combiner les différents types d'objets que nous venons de voir. Ce
sont en fait des sortes de "fourre-tout", mais qui sont particulièrement utiles en
programmation fonctionelle (nous reviendrons dessus plus tard). Il permettent également de
sauvegarder tout un tas de données regroupées en un seul objet.
Il est par exemple possible de combiner les objets que nous avons créé précédement dans une
liste d'objets :
La liste des différents objets est alors visible. Remarquez les numéros entre double crochets
[[]]. Pour aller chercher un des éléments de la liste, on utilise la notation entre deux crochets :
Il est également possible de renommer les éléments d'une liste pour plus de lisibilité
Plus simplement, comme pour les dataframes on nommera les éléments d'une liste lors de sa
création :
mylist <- list(myvec = vec, mychars = char, mymat = mat, mydf = df)
rm(x)
ls()
Points clés
Vous venez de voir :
Comment stocker des données complexes dans des objets R : vecteurs, matrices,
dataframes, listes
Comment connaitre les dimensions de ces objets (longueur d'un vecteur, nb de lignes /
colonnes de matrices et df)
Comment générer des séquences de valeurs numériques, comment concaténer des
vecteurs avec c()
Comment interagir avec des éléments des objets R (éditer, remplacer, rechercher des
données) à l'aide des index
Comment réaliser une comparaison de valeurs et obtenir un résultat logique (avec les
opérateurs ==, >, <, >=, <=)
Comment lire et enregistrer des objets R pour pouvoir les réutiliser
Exercices
Les exercice du TP02 sont accessibles dans le fichier main.r. La solution du précédent TP est
également disponible.
Cours 3
Partie I : caractères, textes et facteurs
Chaînes de caractères
Nous avons vu qu'il est possible de concaténer des chaînes de texte (que l'on apelle strings en
anglais) dans un vecteur. La fonction c() attribue dans des indices différent d'un vecteur
différentes chaîînes de texte. Mais comment fusionner des chaînes de texte ?
# Les diffrentes chaînes de texte sont rangées dans un indice différent du vecteur...
paste("Je", "suis", "en", "bioinfo")
# Les quatres chaînes de texte sont fusionnées en une seule...
Le comportement par défaut de paste est d'insérer un espace entre chacun des éléments. Il est
possible de changer le séparateur avec la chaîne de son choix à l'aide de l'argument "sep"
(pour séparateur).
Facteurs
Nous avons vu et manipulé trois types de classes qu'il est possible d'attribuer à des données
(numeric integer et character). Il existe une quatrième classe qui a une importance majeure
dans l'analyse et le traitement des données, la classe factor, qui est assez liée aux chaînes de
texte.
Les factors permettent de stocker des données qui peuvent prendre un nombre fini et limité de
valeurs différentes (exemple : malade / sain ; asymptomatique / symptomatique /
soin_intensifs). Ils permettent donc de stocker des données catégorielles. Les factors ont une
utilité fondamentale pour la modélisation statistique et plus généralement l'analyse de
données. La classe factor est une particularité de R par rapport à python, et lui confère un
avantage pour le traitement statistique.
Les facteurs permettent de stocker aussi bien des des chaînes de caractères que des nombres
(eg. factor durée d'un traitement : 2 / 5 / 10).
Les facteurs sont créés simplement à l'aide de la fonction factor() qui prend au minimum un
vecteur en argument.
# vecteur numérique
vect_num <- c(1, 2, 1, 1, 2, 2, 2)
class(vect_num)
# vecteur de chaînes de caractères
vect_char <- c("malade", "sain", "malade", "malade", "sain", "sain", "sain")
class(vect_char)
Définir les niveaux d'un facteur permet de s'assurer que l'ensemble des données présentes
appartiennent toutes bien aux catégories du facteur. Une fois les niveaux du facteur définis, il
n'est plus possible de modifier les valeurs du facteur avec autre chose que l'une ou l'autre de
ses catégories.
R devinne les différentes catégories de facteur en fonction des données qui sont présentes
dans le vecteur utilisé pour sa création (on parle de niveau de catégories, ou levels). Les
catégories sont enregistrées par ordre croissant / alphabétique.
Il est toutefois possible de définir des catégories supplémentaires après coup à l'aide de la
fonction levels(), ainsi que changer l'ordre des facteurs au besoin. Changer l'ordre des
catégories de facteurs a son importance pour la représentation graphique de données.
# il est également possible de déclarer des catégories non présentes dans le vecteur
# lors de la création du facteur
# ici le vecteur vect_char ne contiens que "malade" et "sain"
fact_char_2 <- factor(vect_char, levels = c("malade", "sain", "en_remission"))
fact_char_2
# "en remission" n'est pas présent dans le vecteur vect_char
# mais nous venons de l'ajouter en niveau du facteur lors de sa création
table(fact_char)
prop.table(table(fact_char))
# par défaut les chaînes de caractères ne sont pas interprétées comme des facteurs
df$nom
summary(df)
df <- data.frame(nom = c("marie", "paul", "alice", "jean"), age = c(19, 20, 19, 18), note = c(14, 15, 17, 11),
stringsAsFactors = TRUE)
df
Partie II : Itérations
Itérations : les boucles
Les boucles for permettent de réaliser des opérations de manière répétitives, sur des données
différentes, par example :
La syntaxe pour écrire une boucle for a été vue en cours, elle s'écrit en indiquant sur quel
élément faire une répétition entre parenthèses (), et la liste des commandes à répéter entre
accolades {}.
Exemple, reprenons notre vecteur de patients malades et sain. Et écrivons une boucle de
répétition pour afficher chacun des éléments de ce vecteur.
# Création de la boucle
for (indice in 1:7) { print( char[ indice ] ) }
# Il est possible d'utiliser n'importe quelle nom de variable pour définir la répétition
for (i in 1:7) { print( char[ i ] ) }
for (patient in 1:7) { print( char[ patient ] ) }
# Donne la même chose...
# Une fois la boucle définie, il est possible d'enchaîner des commandes différentes, chacune des
commandes sera répétée à chaque tour de la bouche
# Si on veux que le résultat soit affiché dans le terminal, la fonction print() est indispensable dans une
boucle
# Demonstration :
# On créé d'abord un vecteur vide pour pouvoir collecter les données
result <- vector()
# En pratique il est plus efficace de définir la taille du vecteur d'abord
# pour réserver de la mémoire dans l'ordinateur et accélérer les choses
# Mais la commande précédente marche tout aussi bien
result <- vector(length = 7)
# Puis la boucle
for (indice in 1:7) {
result[ indice ] <- nchar( char[ indice ] )
}
Pour résumer, une technique simple à mettre en oeuvre pour récolter des données générées
dans une boucle et d'utiliser un second vecteur, les données étant stockées à un indice du
vecteur détérminé par le "numéro" de la boucle.
La stratégie est la même pour itérer dans des éléments d'un dataframe, une liste, etc.
vec * 10
mat * 10
Pour les exercices de ce TP, vous vous rendrez compte que certains problèmes ne peuvent
toutefois être traités qu'avec des boucles. Dans tous les cas, les exercices d'application de
cette séance ont naturellement pour but de vous faire manipuler des boucles, donc
n'utilisez pas de technique de vectorisation pour cette séance... Nous rediscuterons des bonnes
pratiques pour faire du code efficace plus tard, qui est un enjeu crucial lorsque l'on travaille
sur des données très volumineuses.
Pour aller plus loin : Dans les languages compilés (bas niveau), pour tout calcul répétitif on
est obligé d'utiliser des boucles. Les pythoneux parmis vous connaissent également bien ce
principe. R repose sur des bibliothèques d'algèbre linéaire et de vectorisation du calcul (codé
en language compilé) qui sont très rapides. Les informaticiens ou codeurs formés aux
techniques de code bas-niveau ont tendance à utiliser systématiquement des boucles sous R...
et trouvent le language très lent. Pourtant, utilisé correctement R est souvent aussi, voir plus
rapide que python. Ces particularités expliquent pourquoi R est considéré comme un language
plus "haut-niveau" que python (au sens du code, pas de jugement de valeur ici), mais aussi
perçu à tord comme un langage plus lent que python. Tout dépends en fait de la manière dont
sont utilisés les languages.
Points importants
Vous venez de voir :
Cours 4
Applications : dplyr
Information technique
Replit présente des contraintes techniques particulières pour l'utilisation de librairies. Comme
expliqué lors du cours sur les librairies et applications, une préparation de votre espace a été
réalisée en amont afin d'installer les librairies nécessaires à cette séance de TP et les charger
automatiquement afin de vous faciliter le travail.
Lorsque vous lancez une session de R interactive dans l'interpréteur, vous pouvez vérifier que
dplyr est bien chargé automatiquement. En plus des informations habituelles, le message
suivant est affiché :
Les librairies de cet espace de travail sont également automatiquement chargées lors de
l'execution des scripts (commande Run, ou lors du lancement de tests). Vous n'avez donc rien
à faire de particulier pour utiliser les librairies de ce TP.
N'oubliez pas que si vous voulez tester des librairies dans une installation locale de R (votre
ordinateur), vous devrez au préalable les installer.
Il existe des fonctions de R qui permettent de traiter facilement ces données spéciales. Vous
êtes invité à tester ces outils par vous même dans l'interpréteur avant la séance de TP :
Les exemples qui suivent prendront en entrée les données de l'objet iris que vous avez déjà
manipulé à plusieurs reprises, et qui est un dataframe.
# Mais aussi avec le pipe une fois la librairie dplyr installée et chargée
iris %>% head()
Notez que dans les examples suivant head() ne sert qu'à réduire le nombre de lignes affichées
dans l'interpréteur pour que vous puissiez facilement vérifier les commandes par vous-même.
Pour les données multivariées plus complexes (avec plusieurs facteurs par exemple), il est
possible de compter le nombre de cas regroupés sur plusieurs facteurs. Pour illustrer la
procédure, nous allons modifier les données d'iris.
Il est possible de compter les cas, ou de résumer des cas regroupés sur plusieurs facteurs.
Pour la démonstration on créé une nouvelle catégorie à partir des données d'iris.
# on crée ensuite une nouvelle catégorie de facteur (une nouvelle colonne) appelée cat_sepal_long de
valeur "short" si Sepal.Length est < 5.8 ou de valeur "long" si Sepal.Length est > 5.8, le tout à l'aide de la
fonction cut() de R base
dat$cat_sepal_long <- cut(dat$Sepal.Length, breaks=c(-Inf, 5.8, Inf), labels=c("short", "long"))
# On peut ensuite facilement regrouper les données sur le facteur Species puis cat_sepal_long et compter le
nombre de cas pour chacun de ces facteurs
dat %>% group_by(Species, cat_sepal_long) %>% count()
# On peut également utiliser la fonction summarise() qui permet de réaliser n'importe quel calcul
(statistique ou autre) et de le renvoyer dans une colonne dont on peut choisir le nom
dat %>% group_by(Species, cat_sepal_long) %>% summarise(decompte = n())
La seconde approche donne le même résultat, mais avec un nom de colonne différent
(decompte). Dans les deux cas, l'objet produit est un tibble.
# On filtre pour ne garder que les observations qui ont une valeur de Sepal.Length supérieures à 5.8
iris %>% filter(Sepal.Length > 5.8) %>% nrow()
# cette fois il reste seulement 70 observations
Cette technique est également utile pour lever des ambiguités sur certaines fonctions. Par
exemple, R base contient déjà une fonction qui s'appelle filter(). Les créateurs de dplyr ont
modifié cette fonction pour qu'elle aie un comportement différent, dplyr contiens donc
une autre fonction filter() qui est diffrente. Lors du chargement d'une librairie les fonctions
déjà existantes sont normalement masquées. Pour pouvoir utiliser sans ambiguité une fonction
de l'une des deux librairies, il suffit de les appeler de manière explicite :
# Appel de la fonction de R base
base::filter()
Cours 5
Applications: ggplot2
Information technique
Replit présente des contraintes techniques particulières pour l'utilisation de librairies. Comme
expliqué lors du cours sur les librairies et applications, une préparation de votre espace a été
réalisée en amont afin d'installer les librairies nécessaires à cette séance de TP et les charger
automatiquement afin de vous faciliter le travail.
Lorsque vous lancez une session de R interactive dans l'interfinpréteur, vous pouvez vérifier
que ggplot2 est bien chargé automatiquement. En plus des informations habituelles, le
message suivant est affiché :
Les librairies de cet espace de travail sont également automatiquement chargées lors de
l'execution des scripts (commande Run, ou lors du lancement de tests). Vous n'avez donc rien
à faire de particulier pour utiliser les librairies de ce TP.
N'oubliez pas que si vous voulez tester des librairies dans une installation locale de R (votre
ordinateur), vous devrez au préalable les installer.
Rappels sur l'utilisation de ggplot2
La syntaxe générique de ggplot2 vous a été présentée pendant le précédent cours. Pour rappel,
la fonction ggplot() nécessite d'indiquer 1.les données à utiliser (un dataframe), 2. la manière
de lier les variables à des paramètres graphiques ou aethetics avec aes(), qui est également
passé en argument de la fonction ggplot(), 3. indiquer comment représenter des points à l'aide
de fonctions de représentation du type geom_nomdelafonction() et qui sont précédées du
signe +. La syntaxe générique est donc :
# syntaxe générique, cette commande ne fonctionne pas si les objets
# passés en argument n'existent pas...
ggplot(data = mondataframe, aes(x = variable1, y = variable2, ... )) +
geom_nomFonctionDeRepresentation()
Vous trouverez la cheat sheet ggplot2 dans cet espace de cours qui vous rapelle cette syntaxe,
ainsi que les différentes fonctions de représentation graphique existantes.
Il est également possible de capturer des commandes ggplot dans des objets, pour ajouter plus
facilement des couches de représentation sans avoir à recopier trop de code.
# Commande générique
ggplot(data = mondataframe, aes(x = variable1, y = variable2, ... )) +
geom_nomFonctionDeRepresentation()
# on peu alors afficher facilement le graphique en tapant g, ou capturer ce graphique dans un fichier :
# affiche le graphique
g
# Enfin, il est possible de simplement rajouter des couches de représentation en passant d'autres fonctions
de représentation les unes après les autres, après un signe +
# et ainsi de suite
g <- g + geom_couche3() + geom_couche4()
# Une fois satisfait de la représentation graphique, vous pouvez capturer le graphiquedans un fichier pdf,
png... ou même rds. Ces formats étant différents, ils n'auront naturellement pas la même utilité.
NB: en interactif, n'oubliez pas que vous pouvez afficher les commandes précédement entrées
en navigant avec les flèches haut et bas, et ainsi compléter des commandes facilement.
Boxplot
Il sont produits avec la fonction geom_boxplot(), des groupes (facteurs) peuvent être indiqués
en absisse.
Comme vu en cours, il est possible d'attriber différents paramètres graphiques à des variables
continues ou discrètes (forme, couleur, bordure ou type de points...).
Bar (histogrammes)
Les histogrammes sont produits avec la fonction geom_bar(). Il permettent de produire des
histogrammes de distribution avec des valeurs continues, en comptant le nombre d'occurance
pour chaque valeur.
# Histogramme de distribution
ggplot(data = iris, aes(x = Petal.Width, fill = Species)) + geom_bar()
Il peuvent aussi servir à compter le nombre d'occurance d'un facteur lorsque les données sont
discrètes.
Violin plot
Les violin plots sont produits avec la fonction geom_violin(). Il permettent d'avoir une idée de
la distribution de données continues. Ils ont une utilité comparable aux boxplot pour la
visualisation de distributions, tout en apportant plus d'information.
# Graph simple
ggplot(data = iris, aes(x = Petal.Width, y = Petal.Length, color = Species)) + geom_jitter()
# ajout de facettes par colonnes, le ~ indique que l'on créé des facettes
# en fonction de la variable Species
ggplot(data = iris, aes(x = Petal.Width, y = Petal.Length, color = Species)) + geom_jitter() + facet_grid(~
Species)
# Ou les deux (rangée en fonction des colonnes : rows ~ cols), lorsqu'il y a suffisement de variables
discrètes dans les données
Avec R base, cette représentation nécessite plusieurs étapes. Il faut commencer par calculer
les paramètres d'un modèle (ici linéaire). La modélisation dans R se fait à l'aide du symbole ~
(tilde). Il n'est pas indispensable de connaitre ce type de procédure si vous maîtrisez ggplot,
mais cette démonstration vous permet de comprendre les différences entre les représentations
graphiques R base et ggplot. Ces techniques sont également en lien avec la biostatistique.
y en fonction de x s'écrit: y ~ x, c'est le même principe que pour les facettes ggplot.
Dans R base, il est possible d'ajouter une représentation de droite dans un graphique déjà
préent dans une sortie à l'aide de la fonction abline().