ANCSEP
Appui institutionnel en matière de maîtrise des risques sanitaires et environnementaux TN/14/ENP/HE/44
ATELIER DE FORMATION GESTION ET TRAITEMENT DES DONNEES EN EVALUATION DU RISQUE
\newpageTunis 3-6 janvier 2017
Page vide
\newpage\newpage
M. SANAA1 Les data.frames sont des tableaux à deux dimensions. Leur particularité est de pouvoir stocker des données hétérogènes selon les colonnes. C’est le type d’objet que vous utiliserez le plus dans R., D. CUZZUCOLI et F. AUDIAT-PERRIN
Ce polycopié aborde la gestion et le traitement des données scientifiques dans le cadre d’une évaluation du risque. Vous apprendrez à intégrer vos données dans R, à les avoir dans la structure la plus utile, à les transformer, à les visualiser et à les modéliser. Il s’agit d’acquérir les bonnes pratiques pour une meilleure utilisation des données scientifiques. Vous apprendrez à écrire des procédures R qui assurent la traçabilité, la reproductibilité des analyses des données et aussi un gain de temps considérable par comparaison aux analyses faites sur des outils communs (exemple Excel).
Il s’agit d’appliquer la science des données (en anglais “data science”) qui est une discipline qui s’appuie sur des outils mathématiques, statistiques, informatiques et de visualisation des données. Elle vous permettra de transformer vos données brutes en informations et connaissances. L’objectif de cette formation est de vous aider à apprendre les outils les plus importants dans R qui vous permettent de faire de la science des données. A la fin de cette formation vous aurez les outils pour relever un large éventail de défis liés à la science des données, en utilisant les meilleures parties de R.
Un projet typique de science de données comprend les étapes suivantes:
Science des données
Vous devez tout d’abord importer vos données dans R. ce qui implique en général que vous avez des données stockées dans un fichier ou dans une base de données et que vous les chargez dans un data.frame
2 (http://www.r-project.org/) de R.
Une fois vos données importées, il convient de les ranger. Le rangement des données dans un tableau suppose que chaque colonne est une variable, et chaque ligne est une observation. Le choix de la structure du rangement des données doit être en cohérence avec les traitements souhaités des données.
Une fois que vous avez des données rangées, une première étape commune est de les transformer. La transformation inclut la sélection des observations d’intérêt (comme toutes les personnes d’une ville ou toutes les données de l’année dernière), la création de nouvelles variables qui sont des fonctions de variables existantes et le calcul d’un ensemble de résumé statistiques (comme les comptages ou les moyennes). Une fois que vous avez des données bien rangées avec les variables qu’il faut, vous disposez de deux approches complémentaires pour comprendre les phénomènes étudiés: la visualisation et la modélisation.
R est un langage et un environnement puissants pour les calculs statistiques et les graphiques. C’est un projet du domaine public. Les principaux avantages de R sont sa gratuité et la disponibilité d’aide en ligne. Il est assez similaire à d’autres programmes tels que MatLab (non gratuit), mais plus convivial que les langages de programmation comme C ++ ou Fortran. Vous pouvez utiliser directement R, mais pour des fins pédagogiques, nous préférons utiliser R avec l’interface RStudio (également gratuite). En plus de R et RStudio, nous utiliserons plusieurs packages qui doivent être installés et chargés séparément.
Pour installer R, allez sur le site web de R3 http://www.rstudio.org/ et suivez les étapes suivante:
Pour installer RStudio, allez sur le site web de RStudio4 La fonction ‘seq’ sert à générer des suites de nombres, ici seq(from = 0, to = 80, by = 5): 0, 5, 10, 15, …, 80. et téléchargez la version de votre système d’exploitation. Exécutez le fichier télécharger et répondez à toutes les questions (réponses par défaut).
Une fois que vous avez lancé RStudio vous verrez l’interface suivante. L’interface RStudio est composée de différents panneaux, dont l’arrangement peut être reconfiguré, incluant une console, un navigateur de fichiers et graphiques, l’espace de travail et l’historique des commandes :
Interface de RStudio
Un grand nombre de fonctions, contenus dans différents packages, sont installés dans la version de base du logiciel R. Il est possible (et nous en aurons besoin dans les différents cours de Statistique) d’installer des packages supplémentaires. Pour cela, lorsque vous disposez d’une connexion internet, il suffit d’utiliser la commande install.packages("nom du package")
en indiquant le nom du package que l’on veut installer ou utilser le menu Tools. Il faudra ensuite charger le package à l’aide de la commande library("nom du package")
ou à partir du panneau package.
Pour commencer à découvrir les fonctionalités de R nous allons utiliser deux fichiers de données conso.csv et indiv.csv. Le chargement de ces fichiers se fait à l’aide de la commande read.csv2(), qui permet de lire des fichiers CSV pour lesquels le séparateur de champ est un point-virgule, et le séparateur décimal une virgule. Les données seront associées aux objets conso et indiv à l’aide de l’opérateur =
. Dans ce qui suit, nous supposerons que vous avez bien défini le dossier contenant les fichiers xxx.csv comme dossier de travail, soit à l’aide de la commande setwd() soit via le menu de RStudio (Session/Set Woking directory). Avant de commencer, il est préférable que vous listiez les objets déja présent dans votre environnement de travail et les supprimer (à l’aide de la commande rm()
afin d’éviter toute confusion entre les objets de cette session avec ceux des anciennes sessions.
indiv=read.csv2("indiv.csv")
Les données sont généralement représentées sous la forme d’un tableau rectangulaire dans lequel les variables sont arrangées en colonnes, et les observations en lignes. Sous R, il s’agit de data frame. Une fois que les données sont importées, l’objet indiv sera disponible dans l’environnement de travail, comme on pourra le vérifier avec la commande ls(). Les dimensions du tableau de données peuvent être vérifiées à l’aide de dim(), et la commande names() renvoit le nom des variables.
Visualisation du dossier de travail et de l’environnement de travail. Les fichiers csv sont accessibles via le panneau Files et les objets crées via le panneau Environment
ls()
## [1] "indiv"
dim(indiv)
## [1] 4079 11
names(indiv)
## [1] "cod_com" "agglo9" "loc_log" "nomen" "sexe_ps" "region" "ech"
## [8] "v2_age" "tage" "poidsm" "taillem"
La commande str() fournit un résumé de l’ensemble des variables avec leur type (ou mode de représentation) – int pour les variables numériques, factor pour les variables catégorielles – et un aperçu des 10 premières observations.
str(indiv)
## 'data.frame': 4079 obs. of 11 variables:
## $ cod_com: int 77239 77239 78291 78003 78003 91200 91200 77143 75102 75102 ...
## $ agglo9 : Factor w/ 9 levels "> 200 000 hab. ",..: 9 9 9 4 4 6 6 7 8 8 ...
## $ loc_log: Factor w/ 4 levels "bourg ou village ",..: 1 1 1 1 1 2 2 1 2 2 ...
## $ nomen : int 110006 110007 110020 110021 110025 110034 110046 110057 110067 110071 ...
## $ sexe_ps: Factor w/ 2 levels "femme ","homme ": 1 2 1 1 1 1 2 2 2 1 ...
## $ region : Factor w/ 21 levels "Alsace ","Aquitaine ",..: 20 20 20 20 20 20 20 20 20 20 ...
## $ ech : Factor w/ 2 levels "adultes ","enfants ": 1 1 1 1 1 1 1 1 1 1 ...
## $ v2_age : int 54 70 43 75 39 61 76 52 38 32 ...
## $ tage : Factor w/ 8 levels "11-14 ans ","15-17 ans ",..: 7 8 6 8 6 7 8 7 6 4 ...
## $ poidsm : Factor w/ 428 levels "10","100","100.300003051758",..: 367 302 419 210 230 210 286 367 324 233 ...
## $ taillem: int 162 170 170 152 165 152 163 175 181 173 ...
Une autre commande utile pour vérifier la structure des données est summary()
qui fournit un résumé descriptif univarié pour chaque variable. Dans le cas des variables numériques, R indique les principaux indicateurs de tendance centrale (moyenne et médiane) et de dispersion (étendue, intervalle inter-quartile), ainsi que le nombre de valeurs manquantes représentées par le symbole NA. Dans le cas des variables catégorielles, R fournit un tableau d’effectifs, c’est-à-dire le nombre d’observations associées à chacune des modalités de la variable.
summary(indiv)
## cod_com agglo9
## Min. : 1053 rural :986
## 1st Qu.:33281 > 200 000 hab. :773
## Median :59299 100 000 à 200 000 hab. :609
## Mean :54810 agglo paris :535
## 3rd Qu.:76627 50 000 à 100 000 hab. :324
## Max. :95637 2 000 à 5 000 hab. :267
## (Other) :585
## loc_log nomen sexe_ps
## bourg ou village :1047 Min. :110006 femme :2304
## centre ville :1148 1st Qu.:115313 homme :1775
## habitat dispersé : 446 Median :171728
## quartier périphérique :1438 Mean :175486
## 3rd Qu.:241547
## Max. :267394
##
## region ech v2_age
## Région Parisienne : 601 adultes :2624 Min. : 3.00
## Rhône-Alpes : 343 enfants :1455 1st Qu.:14.00
## Languedoc : 254 Median :32.00
## Aquitaine : 244 Mean :33.51
## Nord : 227 3rd Qu.:51.00
## Provence Côte D'azur : 227 Max. :79.00
## (Other) :2183
## tage poidsm taillem
## 35-49 ans :837 60 : 92 Min. : 86.0
## 50-64 ans :750 65 : 90 1st Qu.:155.0
## 3-10 ans :574 58 : 84 Median :164.0
## 11-14 ans :456 62 : 82 Mean :159.9
## 25-34 ans :432 63 : 79 3rd Qu.:172.0
## 15-17 ans :425 (Other):3325 Max. :202.0
## (Other) :605 NA's : 327 NA's :326
Pour afficher l’ensemble des observations recueillies pour une variable données, vous taperez le nom de cette variable préfixé du nom du data frame suivi du signe $
. L’expression indiv$v2_age
désignera ainsi les valeurs prises par la variable v2_age
dans le data frame indiv. Plutôt que d’afficher l’ensemble des valeurs, on peut vouloir limiter l’affichage à certaines observations, que l’on désignera par leur numéro. On peut ainsi choisir d’afficher, la première, les deux premières, ou la première et la dixième observation à l’aide des instructions suivantes :
indiv$v2_age[1]
## [1] 54
indiv$v2_age[c(1,2)]
## [1] 54 70
indiv$v2_age[c(1,10)]
## [1] 54 32
Il est également possible d’afficher un ensemble d’observations consécutives en utilisant la notation [i:j] où i et j désignent, respectivement, le premier et le dernier numéro d’observation. Pour afficher les 5 premières observations, on utilisera donc la commande :
indiv$v2_age[1:5]
## [1] 54 70 43 75 39
En fait, il existe une commande, head(), qui permet d’afficher les premières observations d’une variable. Par défaut, head() affichera les 6 premières observations, comme on pourra le vérifier dans l’aide en ligne. Cette valeur par défaut peut être modifiée en ajoutant l’option n=20, par exemple.
La commande summary() fonctionne également avec une variable et fournit, comme dans le cas d’un data frame, un résumé numérique de la distribution de la variable selon son type.
summary(indiv$taillem)
## Min. 1st Qu. Median Mean 3rd Qu. Max. NA's
## 86.0 155.0 164.0 159.9 172.0 202.0 326
En plus des résumés statistiques la commande summary() renseigne le nombre de données manquantes (NA’s) pour la variable taille. Le minimum observé peut être obtenu avec la commande min(). Or dans le cas précis de la variable taille, la commande renvoie la valeur NA. Pour contourner ce problème, vous devez indiquer explicitement à R ce que vous souhaitez faire des valeurs manquantes. Par défaut, R ne supprime pas les valeurs manquantes, comme vous pouvez le vérifier dans l’aide en ligne (na.rm=FALSE), et se contente de renvoyer la valeur NA pour signaler à l’utilisateur que certaines données sont manquantes. Pour supprimer les données manquantes utilisez l’argument (na.rm=TRUE).
min(indiv$taillem)
## [1] NA
min(indiv$taillem,na.rm=TRUE)
## [1] 86
L’étendue des valeurs observées s’obtient avec range() qui, contrairement à min(), est une commande qui renvoie des résultats multiples (dans ce cas, le minimum et le maximum de la variable).
range(indiv$v2_age, na.rm=TRUE)
## [1] 3 79
range(indiv$taillem, na.rm=TRUE)
## [1] 86 202
En général les variables qualitatives sont codées en facteur (factor). Pour connaître les différente modalité d’une variable qualitative, utilisez la commande unique. Pour déterminer le nombre d’individus par modalité, utilisez la commande table().
unique(indiv$loc_log)
## [1] bourg ou village centre ville quartier périphérique
## [4] habitat dispersé
## 4 Levels: bourg ou village centre ville ... quartier périphérique
unique(indiv$sexe_ps)
## [1] femme homme
## Levels: femme homme
table(indiv$sexe_ps)
##
## femme homme
## 2304 1775
Il est parfois utile de recoder en variable qualitative des variables continues à l’origine. Par exemple, avec la variable age, il serait tout à fait possible de créer une variable age.cat avec des classes d’amplitudes égales à 5 ans à l’aide de la commande cut(). Les limites des classes sont renseignées avec breaks=seq(0,80,5)
5 La fonction paste() est utilisée pour récupérer les vraies valeurs et non pas leurs classes
indiv$age.cat=cut(indiv$v2_age, breaks=seq(0,80,5))
table(indiv$age.cat)
##
## (0,5] (5,10] (10,15] (15,20] (20,25] (25,30] (30,35] (35,40] (40,45]
## 163 411 585 405 191 194 251 304 280
## (45,50] (50,55] (55,60] (60,65] (65,70] (70,75] (75,80]
## 250 293 260 174 139 113 66
Si vous cherchez à créer une variable age.cat2 à 4 classes d’effectifs équilibrés, utilisez la commande quantile() qui permet de générer un quartilage de la variable. Il est important de préciser l’option include.lowest=TRUE qui permettra d’inclure l’observation dont l’âge vaut l’âge minimal, puisque par défaut les intervalles ont des bornes ouvertes (c’est-à-dire n’incluant pas) à gauche. Exemple :
indiv$age.cat2=cut(indiv$v2_age,breaks=quantile(indiv$v2_age),include.lowest=TRUE)
table(indiv$age.cat2)
##
## [3,14] (14,32] (32,51] (51,79]
## 1030 1010 1059 980
Il arrive souvent lors d’importation de données dans R que certaines variables n’aient pas le format adéquat. Dans le cas précis, nous avons remarqué que la variable poids a été interprétée comme variable qualitative (Factor). Il est possible de transformer cette variable en numérique à l’aide de la fonction as.numeric() et paste()6 Pour créer une fonction on utilse la structure suivante: nomdemafonction=function(variable1,variable2…) {ici on met le contenu de la fonction…}
indiv$poids=as.numeric(paste(indiv$poidsm))
summary(indiv$poids)
## Min. 1st Qu. Median Mean 3rd Qu. Max. NA's
## 10.00 48.00 61.00 59.79 73.00 171.00 327
Il est conseillé de sauvegarder vos données au format RData, qui est un format propre au logiciel R. Cela facilite l’archivage de résultats intermédiaires ou l’enregistrement d’un tableau de données nettoyé (recodage de valeurs manquantes ou modalités de variables qualitative, correction des erreurs de saisie, etc.) ou augmenté de variables auxiliaires. Pour cela, vous utiliserez la commande save(). La commande load() permet quant à elle de recharger des données sauvegardées au format RData. L’extension du ficher peut être indifféremment RData ou rda.
save(indiv,file ="indiv.rda")
Les commandes entrées dans le panneau Console sont immédiatement exécutées par R. Il est, cependant, conseillé de les enregistrer directement dans un script de commandes R, ce qui permet de reproduire les analyses ultérieurement. Dans l’éditeur de RStudio, il suffit d’écrire les commandes telles que vous les entrerez sous la console et il est possible d’exécuter directement la ligne sur laquelle le curseur se situe ou une sélection multiple à la console en cliquant sur le bouton RUN. Une fois enregistrées dans un fichier script R (extension .r ou .R), il est possible d’exécuter l’ensemble des instructions à l’aide de la commande source(). Attention, dans ce cas, R n’affiche pas nécessairement l’intégralité des résultats qui sont affichés en mode interactif, à moins d’ajouter l’option echo=TRUE.
Pour accéder à une variable contenue dans un data frame, on utilise son nom préfixé du symbole $ et du nom du data frame.
head(indiv$v2_age)
## [1] 54 70 43 75 39 61
Une commande équivalente consiste à utiliser le numéro de position de la variable parmi les colonnes du data frame (ici, la variable v2_age se trouve dans la huitième colonne) ou d’utiliser le nom de la variable (entre quotes): indiv[,8] ou indiv[,“v2_age”].
Considérons la variable loc_log qui indique le type de commune où habitent les répondants. Si seulement un sous-groupe des répondants vous intéresse, par exemple ceux qui habite en centre ville, vous pouvez utiliser un filtre logique avec l’opérateur == (égalité logique) pour sélectionner les observations remplissant cette condition. On pourra dresser un tableau d’effectifs en utilisant le même principe via table().
head(indiv$loc_log == "centre ville ")
## [1] FALSE FALSE FALSE FALSE FALSE TRUE
# j'ai ajouté un espace à la fin de centre ville
#car celui qui a saisi les données avait fait de même!!
table(indiv$loc_log == "centre ville ")
##
## FALSE TRUE
## 2931 1148
La commande which() permet de renvoyer les numéros d’observations (lignes du tableau) remplissant la condition.
head(which(indiv$loc_log == "centre ville "))
## [1] 6 7 9 10 11 12
Une telle instruction peut être utilisée pour indexer les observations d’une autre variable, par exemple l’âge des personnes habitant en centre ville:
head(indiv$v2_age[which(indiv$loc_log == "centre ville ")])
## [1] 61 76 38 32 69 29
Toutefois, R offre une commande plus intéressante qui permet de sélectionner à la fois des observations remplissant une ou plusieurs conditions, et un sous-ensemble de variables. Il s’agit de la commande subset() qui prend comme premier argument le nom du data frame sur lequel on souhaite opérer, comme deuxième argument un ou plusieurs filtres logiques à appliquer aux lignes, et comme troisième argument le numéro ou le nom des variables à sélectionner.
selection=subset(indiv,loc_log=="centre ville ")
head(selection)
## cod_com agglo9 loc_log nomen sexe_ps
## 6 91200 5 000 à 10 000 hab. centre ville 110034 femme
## 7 91200 5 000 à 10 000 hab. centre ville 110046 homme
## 9 75102 agglo paris centre ville 110067 homme
## 10 75102 agglo paris centre ville 110071 femme
## 11 75105 agglo paris centre ville 110081 homme
## 12 75110 agglo paris centre ville 110110 femme
## region ech v2_age tage poidsm taillem age.cat
## 6 Région Parisienne adultes 61 50-64 ans 53 152 (60,65]
## 7 Région Parisienne adultes 76 65 ans et + 66.5 163 (75,80]
## 9 Région Parisienne adultes 38 35-49 ans 73 181 (35,40]
## 10 Région Parisienne adultes 32 25-34 ans 58 173 (30,35]
## 11 Région Parisienne adultes 69 65 ans et + 71.5 173 (65,70]
## 12 Région Parisienne adultes 29 25-34 ans 60 165 (25,30]
## age.cat2 poids
## 6 (51,79] 53.0
## 7 (51,79] 66.5
## 9 (32,51] 73.0
## 10 (14,32] 58.0
## 11 (51,79] 71.5
## 12 (14,32] 60.0
Les filtres sur les observations peuvent être multiples et on utilisera le symbole & pour désigner une conjonction (« et » logique) de critères de sélection des lignes du data frame.
selection=subset(indiv,loc_log=="centre ville " & v2_age>60,
c(v2_age,loc_log,poids))
head(selection)
## v2_age loc_log poids
## 6 61 centre ville 53.0
## 7 76 centre ville 66.5
## 11 69 centre ville 71.5
## 15 61 centre ville 48.3
## 23 66 centre ville 52.0
## 29 67 centre ville 78.0
Le tableau d’effectifs pour la variable age.cat que nous avions construite peut être stocké dans un objet que nous appellerons tab.
tab=table(indiv$age.cat)
À partir du moment où le tableau d’effectifs a été sauvegardé dans un objet,il devient possible d’effectuer un certain nombre d’opération élémentaires comme, par exemple, compter le nombre total d’observations à l’aide de la commande sum(). Les opérations arithmétiques s’effectuant élément par élément sous R, il est même possible d’obtenir les fréquences relatives par simple division des éléments de tab avec le total sum(tab).
sum(tab)
## [1] 4079
tab/sum(tab)
##
## (0,5] (5,10] (10,15] (15,20] (20,25] (25,30]
## 0.03996077 0.10075999 0.14341750 0.09928904 0.04682520 0.04756068
## (30,35] (35,40] (40,45] (45,50] (50,55] (55,60]
## 0.06153469 0.07452807 0.06864428 0.06128953 0.07183133 0.06374111
## (60,65] (65,70] (70,75] (75,80]
## 0.04265751 0.03407698 0.02770287 0.01618044
Cependant, il existe une commande dont le rôle est précisément de fournir les fréquences relatives, prop.table(), et qui se révélera beaucoup plus utile dans le cas des tableaux à deux entrées.
prop.table(tab)
##
## (0,5] (5,10] (10,15] (15,20] (20,25] (25,30]
## 0.03996077 0.10075999 0.14341750 0.09928904 0.04682520 0.04756068
## (30,35] (35,40] (40,45] (45,50] (50,55] (55,60]
## 0.06153469 0.07452807 0.06864428 0.06128953 0.07183133 0.06374111
## (60,65] (65,70] (70,75] (75,80]
## 0.04265751 0.03407698 0.02770287 0.01618044
Notons également qu’il est possible de limiter l’affichage des décimales à l’aide de round(), en précisant le nombre de décimales à afficher en deuxième argument. Si au lieu des fréquences relatives on souhaite afficher des pourcentages, on multipliera simplement les fréquences relatives renvoyées par prop.table()par 100.
round(prop.table(tab)*100, 1)
##
## (0,5] (5,10] (10,15] (15,20] (20,25] (25,30] (30,35] (35,40] (40,45]
## 4.0 10.1 14.3 9.9 4.7 4.8 6.2 7.5 6.9
## (45,50] (50,55] (55,60] (60,65] (65,70] (70,75] (75,80]
## 6.1 7.2 6.4 4.3 3.4 2.8 1.6
Distribution des classes d’âge
barplot(prop.table(tab) * 100,
ylab="Proportion", col="cornflowerblue",
border=NA, ylim=c(0, 15), las=1)
La commande hist() permet de représenter la distribution d’une variable numérique (continue ou discrète) sous forme d’effectif ou de densité. Le nombre de classes, ainsi que la largeur des intervalles de classe, peuvent être paramétrés à l’aide des options nclass= et breaks=. La figure 5 montre une application de cette commande pour la variable poids. Notons qu’une courbe de densité a été ajoutée à l’histogramme. Pour cela, vous utilisez la commande lines() qui permet de travailler sur la même fenêtre graphique et superposer plusieurs éléments graphiques. Le nombre total d’observations peut être ajouté au graphique, à l’aide de paste() qui permet de juxtaposer du texte libre et, par exemple, des expressions R.
hist(indiv$poids, nclass=25, prob=TRUE, col="cornflowerblue", border="white",
xlim=c(10,120), main="", xlab="Poids en Kg", ylab="Densité")
lines(density(indiv$poids, na.rm=TRUE), lwd=2, col="orange")
text(20, 0.015, paste("N =", sum(complete.cases(indiv$poids))), cex=0.8)
Histogramme et densité des poids
Nous pouvons tester la différence des âges entre le groupe des hommes et le groupe des femmes à l’aide d’un test t:
ttres = t.test(v2_age ~sexe_ps , data=indiv)
print(ttres)
##
## Welch Two Sample t-test
##
## data: v2_age by sexe_ps
## t = 1.6866, df = 3733.1, p-value = 0.09175
## alternative hypothesis: true difference in means is not equal to 0
## 95 percent confidence interval:
## -0.1802731 2.4000662
## sample estimates:
## mean in group femme mean in group homme
## 33.99609 32.88620
Le test t suppose que la variable âge soit distribuée selon une loi Normale et l’égalité des variances intra-groupes. Lorsque ces conditions ne sont pas satisfaites, il convient d’utiliser des tests non-paramètrique.
with(indiv, wilcox.test(v2_age ~ sexe_ps, correct=FALSE))
##
## Wilcoxon rank sum test
##
## data: v2_age by sexe_ps
## W = 2120000, p-value = 0.0437
## alternative hypothesis: true location shift is not equal to 0
ksres = with(indiv, ks.test(v2_age[sexe_ps=="femme "], v2_age[sexe_ps=="homme "]))
print(ksres)
##
## Two-sample Kolmogorov-Smirnov test
##
## data: v2_age[sexe_ps == "femme "] and v2_age[sexe_ps == "homme "]
## D = 0.061203, p-value = 0.001094
## alternative hypothesis: two-sided
Nous pouvons également tracer les fonctions de densité estimées de l’âge pour les deux groupes, et marquer certaines zones du graphique afin d’illuster le chevauchement des deux tracés. Afin d’automatiser cette tâche, vous pouvez créer votre propre fonction7 La fonction ifelse() est utilisée avec trois arguments, la condition, le résultat si la condition est vraie et le résultat si la condition est fausse. (plotdens)
plotdens = function(x,y, mytitle, mylab) {
densx = density(x)
densy = density(y)
plot(densx, main=mytitle, lwd=3, xlab=mylab, ylab="Densité",
ylim=c(0,max(max(densx$y),max(densy$y))),bty="l",cex.main=0.8)
lines(densy, lty=1, col=2, lwd=3)
xvals = c(densx$x, rev(densy$x))
yvals = c(densx$y, rev(densy$y))
polygon(xvals, yvals, col="cornflowerblue")
}
Une fois exécutée la fonction plotdens peut être appelée comme les autres fonctions de R:
mytitle = paste("Test de Kolmogorov-Smirnov D=", round(ksres$statistic, 3),
" p=", round(ksres$p.value, 4), sep="")
with(indiv, plotdens(v2_age[sexe_ps=="femme "], v2_age[sexe_ps=="homme "],
mytitle=mytitle, mylab="âge (années)"))
legend(60, .02, legend=c("femme", "homme"), col=1:2, lty=1, lwd=2)
Comparer deux fonctions de densité
Considérons maintenant la variable âge et la variable type du lieu d’habitation. Vous pouvez obtenir les résumés des distributions avec summary() pour la variable quantitative et table() pour la variable qualitative.
summary(indiv$v2_age)
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 3.00 14.00 32.00 33.51 51.00 79.00
table(indiv$loc_log)
##
## bourg ou village centre ville habitat dispersé
## 1047 1148 446
## quartier périphérique
## 1438
nous allons créer une nouvelle variable habitation: avec les modalités 1:“centre ville” et 0: “non centre ville”8 La fonction sort() appliquée à table a permis de trier le tableau des fréquences dans l’ordre croissant des effectifs..
indiv$habitation=ifelse(indiv$loc_log=="centre ville ",1,0)
## vérification
table(indiv$habitation)
##
## 0 1
## 2931 1148
Plutôt que d’utiliser des histogrammes pour représenter la distribution des poids selon le lieu d’habitation, il est parfois préférable d’utiliser des courbes de densité, qui peuvent être superposées dans le même graphique.
Courbes de densité de l’âge en fonction du type de lieu d’habitation
plot(density(indiv$v2_age[indiv$habitation == 1],
na.rm=TRUE), lwd=2, col="orange", xlim=c(19,83),
main="")
lines(density(indiv$v2_age[indiv$habitation == 0],
na.rm=TRUE), lwd=2,col="deepskyblue4")
Pour calculer la moyenne des âges par type de lieu d’habitation, R propose différentes commandes qui permettent d’appliquer une instruction à des sous-ensembles d’observations définis par une variable qualitative. En plus de la commande by(), il existe tapply() qui nécessite de spécfier les arguments suivants: la vraible numérique (exemple: âge), le facteur permettant de définir les groupes (habitation), et la commande (mean), suivie éventuellement de ses propres options (na.rm=TRUE):
tapply(indiv$v2_age, indiv$habitation, mean, na.rm=TRUE)
## 0 1
## 33.37871 33.85627
Le calcul de la moyenne par groupe peut être réalisé à l’aide de la fonction aggregate(). Elle fonctionne comme tapply() mais accepte une notation par formule et le résultat renvoyer est un data.frame.
aggregate(v2_age ~ habitation, data=indiv, mean)
## habitation v2_age
## 1 0 33.37871
## 2 1 33.85627
La fonction aggregate() peut être utilisée pour calculer d’autre statistique que la moyenne. Par exemple, pour calculer les variance:
aggregate(v2_age ~ habitation, data=indiv, var)
## habitation v2_age
## 1 0 436.8893
## 2 1 411.1746
Les BoxPlots ou boîte à moustaches peuvent être utilisés pour résumer la distribution des âges selon le lieu d’habitation. Boxplot utilise le même principe de formule que la fonction aggrgate().
Diagrammes boîtes à moustaches
boxplot(v2_age ~ habitation, data=indiv,
xlab="Habitation 1: centre ville, 0: autres",
ylab="Âge (années)",
col="cornflowerblue", border="cornflowerblue")
Explication du diagramme Boxplot: Un box-plot est un graphique simple composé d’un rectangle duquel deux segments sortent afin de représenter certains éléments des données:
La valeur centrale du graphique est la médiane (il existe autant de valeurs supérieures qu’inférieures à cette valeur dans l’échantillon).
Les bords du rectangle sont les quartiles (Pour le bord inférieur, un quart des observations ont des valeurs plus petites et trois quart ont des valeurs plus grandes, le bord supérieur suit le même raisonnement).
*Les extrémités des moustaches sont calculées en utilisant 1.5 fois l’espace interquartile (la distance entre le 1er et le 3ème quartile).
Explication du diagramme à moustaches
Diagrammes en secteurs
pie(table(indiv$loc_log),cex=1.3)
Mais c’est une mauvaise idée. En effet, la documentation de la fonction pie() nous dit : Pie charts are a very bad way of displaying information. The eye is good at judging linear measures and bad at judging relative areas. A bar chart or dot chart is a preferable way of displaying this type of data. Il est donc préférable de construire le graphe de Cleveland à l’aide de la fonction dotchart() après avoir trier les données de la table9 En utilisant la syntaxe suivante: fun <- function(arguments) {expression}
dotchart(sort(table(indiv$loc_log)), pch = 20,col=1:4,cex=0.8)
Graphe de Cleveland
Pour croiser deux variables numériques, vous pouvez utiliser un nuage de points, où chaque point représente un individu. Exemple :
plot(x = indiv$taillem, y = indiv$poids, pch = 20,
xlab = "Taille en cm", ylab = "Poids en kg", las = 1)
Nuage de points
L’exemple suivant montre comment il est possible de représenter un nuage de points par groupe:
plot(x = indiv$taillem[indiv$sexe_ps=="femme "], y = indiv$poids[indiv$sexe_ps=="femme "],pch=22,
xlab = "Taille en cm", ylab = "Poids en kg", las = 1,col=1)
points(indiv$taillem[indiv$sexe_ps=="homme "], y = indiv$poids[indiv$sexe_ps=="homme "],col=2,pch=25)
legend(90, 120, legend=c("femme", "homme"), col=1:2,lty=0, lwd=2,pch=c(22,25))
Nuage de points par groupe
Sous R, les éléments de base sont des objets : vecteurs, matrices, listes …, sur lesquels sont appliquées des fonctions qui fournissent des résultats numériques et graphiques. Ces objets se différencient par leur mode décrivant leur contenu, et leur classe décrivant leur structure. Les objets atomiques sont de mode homogène et les objets récursifs (listes) sont de mode hétérogène.
Les différents modes sont null (objet vide), logical, numeric, complex, character. Les classes d’objets les plus courantes sont : vector, matrix, array, factor, data.frame, list. On peut avoir des vecteurs, matrices, tableaux, … de mode null (objet vide), logical (TRUE, FALSE, NA), numeric, complex, character tandis que les listes et les data frame peuvent être composés d’éléments hétérogènes. Une confusion entre classes d’objets dans l’appel d’une fonction est la source d’erreur la plus fréquente.
Modes disponibles et contenus correspondants
Mode | Contenu |
---|---|
numeric | nombre réels |
complex | nombres complexes |
logical | valeurs booléennes(vrai/faux) |
character | chaînes de caractères |
function | fonction |
list | données quelconques |
expression | expression non évaluée |
Les fonctions is/as permettent de vérifier ou de contraindre (lorsque c’est possible) le type d’objet. Exemples:
x=3
x
## [1] 3
is.complex(x)
## [1] FALSE
as.complex(x)
## [1] 3+0i
as.character(x)
## [1] "3"
as.integer(T)
## [1] 1
as.integer(F)
## [1] 0
Les caractères permis pour les noms d’objets sont les lettres minuscules a–z et majuscules A–Z, les chiffres 0–9, le point « . » et le caractère de soulignement « _ ». Selon l’environnement linguistique de l’ordinateur, il peut être permis d’utiliser des lettres accentuées, mais cette pratique est fortement déconseillée puisqu’elle risque de nuire à la portabilité du code. voici quelques remarques importantes sur l’attribution des noms aux objets:
NA_integer_
, NA_real_
, NA_complex_
, NA_character_
,…, ..1, ..2, etc.Un vecteur regroupe des éléments de même type. La création d’un vecteur peut se faire par la commande c(e1,e2,…). On peut également générer une séquence avec la commande seq(a,b,t) débutant par a inférieure ou égale à b et de pas t ; rep(x,n) est un vecteur répétant n fois l’élément x.
v=c(2,6,7,10,11,27,28,12,9,0)
v
## [1] 2 6 7 10 11 27 28 12 9 0
is.vector(v)
## [1] TRUE
c(1,2,4,"cinq")
## [1] "1" "2" "4" "cinq"
Séquences et Répétitions
1:10
## [1] 1 2 3 4 5 6 7 8 9 10
seq(from=1,to=10,by=0.5)
## [1] 1.0 1.5 2.0 2.5 3.0 3.5 4.0 4.5 5.0 5.5 6.0 6.5 7.0 7.5
## [15] 8.0 8.5 9.0 9.5 10.0
seq(1,40,by=5)
## [1] 1 6 11 16 21 26 31 36
seq(-5,20,length=5)
## [1] -5.00 1.25 7.50 13.75 20.00
rep(5,times=10)
## [1] 5 5 5 5 5 5 5 5 5 5
rep(c(1,2),3)
## [1] 1 2 1 2 1 2
rep(c(1,2),each=3)
## [1] 1 1 1 2 2 2
e = rep(1,3)
e
## [1] 1 1 1
Extraction dans un vecteur par [ ] et valeurs manquantes
v
## [1] 2 6 7 10 11 27 28 12 9 0
v[2];v[2:3];v[-3]
## [1] 6
## [1] 6 7
## [1] 2 6 10 11 27 28 12 9 0
# attention aux indices :
v[-(1:2)]
## [1] 7 10 11 27 28 12 9 0
# NA (Not Available) signale une donnée manquante
v[3]=NA;v;summary(v)
## [1] 2 6 NA 10 11 27 28 12 9 0
## Min. 1st Qu. Median Mean 3rd Qu. Max. NA's
## 0.00 6.00 10.00 11.67 12.00 28.00 1
is.na(v)
## [1] FALSE FALSE TRUE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
# fonctions "any" et "all"
any(is.na(v));all(is.na(v))
## [1] TRUE
## [1] FALSE
Labels et opérations
f = c(a=12,b=26,c=32,d=41);f
## a b c d
## 12 26 32 41
names(f);f["a"]
## [1] "a" "b" "c" "d"
## a
## 12
names(f)=c("a1","a2","a3","a4")
f>30;f[f>30] # noter les différences
## a1 a2 a3 a4
## FALSE FALSE TRUE TRUE
## a3 a4
## 32 41
which(f>30)
## a3 a4
## 3 4
f[2] = 22;f+100
## a1 a2 a3 a4
## 112 122 132 141
cos(f);length(f);sum(f)
## a1 a2 a3 a4
## 0.8438540 -0.9999608 0.8342234 -0.9873393
## [1] 4
## [1] 107
t(f) # transposition
## a1 a2 a3 a4
## [1,] 12 22 32 41
e=rep(2,4); 2*e; 2+e
## [1] 4 4 4 4
## [1] 4 4 4 4
e+f ; e*f # opérations terme à terme
## a1 a2 a3 a4
## 14 24 34 43
## a1 a2 a3 a4
## 24 44 64 82
f[2] = 22;f+100;f+v # un problème ?
## a1 a2 a3 a4
## 112 122 132 141
## [1] 14 28 NA 51 23 49 60 53 21 22
cos(f);length(f);sum(f)
## a1 a2 a3 a4
## 0.8438540 -0.9999608 0.8342234 -0.9873393
## [1] 4
## [1] 107
t(f) # transposition
## a1 a2 a3 a4
## [1,] 12 22 32 41
e=rep(2,4); 2*e; 2+e
## [1] 4 4 4 4
## [1] 4 4 4 4
e+f ; e*f # opérations terme à terme
## a1 a2 a3 a4
## 14 24 34 43
## a1 a2 a3 a4
## 24 44 64 82
t(f)%*%e # produit scalaire
## [,1]
## [1,] 214
a<-c(3,-1,5,2,-7,3,9)
abs(a);sort(a);order(a)
## [1] 3 1 5 2 7 3 9
## [1] -7 -1 2 3 3 5 9
## [1] 5 2 4 1 6 3 7
a<-c(3,-1,5,2,-7,3,9)
abs(a);sort(a);order(a)
## [1] 3 1 5 2 7 3 9
## [1] -7 -1 2 3 3 5 9
## [1] 5 2 4 1 6 3 7
Un facteur est un vecteur avec une liste prédéfinie de valeurs, les niveaux (levels). Cela correspond typiquement à une variable qualitative nominale.
vect=c("a","b","c","b","b","a")
vect
## [1] "a" "b" "c" "b" "b" "a"
vect.f=as.factor(vect)
vect.f
## [1] a b c b b a
## Levels: a b c
as.integer(vect.f)
## [1] 1 2 3 2 2 1
as.character(vect.f)
## [1] "a" "b" "c" "b" "b" "a"
Comme les vecteurs, les matrices sont de type quelconque mais ne contiennent que des éléments de même nature. Pour créer une matrice, on utilise la commande matrix(vec,nrow=n,ncol=p) où vec est le vecteur contenant les éléments de la matrice de taille n par p, qui seront rangés en colonne sauf si l’option byrow=T est utilisée.
A = matrix(1:15,ncol=5);A
## [,1] [,2] [,3] [,4] [,5]
## [1,] 1 4 7 10 13
## [2,] 2 5 8 11 14
## [3,] 3 6 9 12 15
B = matrix(1:15,nc=5,byrow=T)
B2=B;B2[1,1]="xxx";B2
## [,1] [,2] [,3] [,4] [,5]
## [1,] "xxx" "2" "3" "4" "5"
## [2,] "6" "7" "8" "9" "10"
## [3,] "11" "12" "13" "14" "15"
cbind(A,B);rbind(A,B) # concaténations
## [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
## [1,] 1 4 7 10 13 1 2 3 4 5
## [2,] 2 5 8 11 14 6 7 8 9 10
## [3,] 3 6 9 12 15 11 12 13 14 15
## [,1] [,2] [,3] [,4] [,5]
## [1,] 1 4 7 10 13
## [2,] 2 5 8 11 14
## [3,] 3 6 9 12 15
## [4,] 1 2 3 4 5
## [5,] 6 7 8 9 10
## [6,] 11 12 13 14 15
A[1,3];A[,2];B[2,] # composants
## [1] 7
## [1] 4 5 6
## [1] 6 7 8 9 10
A[1:3,2:4]
## [,1] [,2] [,3]
## [1,] 4 7 10
## [2,] 5 8 11
## [3,] 6 9 12
g = seq(0,1,length=20)
C = matrix(g,nrow=4)
dim(C)
## [1] 4 5
C[C[,1]>0.1,]
## [,1] [,2] [,3] [,4] [,5]
## [1,] 0.1052632 0.3157895 0.5263158 0.7368421 0.9473684
## [2,] 0.1578947 0.3684211 0.5789474 0.7894737 1.0000000
# ranunif : tirage aléatoire uniforme
D = matrix(runif(16),ncol=4)
D>0.5
## [,1] [,2] [,3] [,4]
## [1,] TRUE FALSE TRUE FALSE
## [2,] TRUE TRUE FALSE FALSE
## [3,] FALSE FALSE FALSE TRUE
## [4,] TRUE FALSE TRUE FALSE
D[D[,1]>0.5,2]
## [1] 0.478810205 0.942519202 0.008980543
A+B;A*B # opérations terme à terme
## [,1] [,2] [,3] [,4] [,5]
## [1,] 2 6 10 14 18
## [2,] 8 12 16 20 24
## [3,] 14 18 22 26 30
## [,1] [,2] [,3] [,4] [,5]
## [1,] 1 8 21 40 65
## [2,] 12 35 64 99 140
## [3,] 33 72 117 168 225
cos(A); cos(A[1:2,1:2])
## [,1] [,2] [,3] [,4] [,5]
## [1,] 0.5403023 -0.6536436 0.7539023 -0.839071529 0.9074468
## [2,] -0.4161468 0.2836622 -0.1455000 0.004425698 0.1367372
## [3,] -0.9899925 0.9601703 -0.9111303 0.843853959 -0.7596879
## [,1] [,2]
## [1,] 0.5403023 -0.6536436
## [2,] -0.4161468 0.2836622
# inversion
solve(A[1:2,1:2])
## [,1] [,2]
## [1,] -1.6666667 1.3333333
## [2,] 0.6666667 -0.3333333
# produit matriciel
t(A) %*% B
## [,1] [,2] [,3] [,4] [,5]
## [1,] 46 52 58 64 70
## [2,] 100 115 130 145 160
## [3,] 154 178 202 226 250
## [4,] 208 241 274 307 340
## [5,] 262 304 346 388 430
A[1:2,1:2] %*% B[1:2,1:3]
## [,1] [,2] [,3]
## [1,] 25 30 35
## [2,] 32 39 46
t(B); diag(A)
## [,1] [,2] [,3]
## [1,] 1 6 11
## [2,] 2 7 12
## [3,] 3 8 13
## [4,] 4 9 14
## [5,] 5 10 15
## [1] 1 5 9
apply(A,2,sum)
## [1] 6 15 24 33 42
apply(D,1,max)
## [1] 0.7672717 0.9425192 0.7347609 0.7115704
# Eléments propres
s=eigen(A[1:2,2:3])
s$values
## [1] 12.244998 -0.244998
s$vectors
## [,1] [,2]
## [1,] -0.6472056 -0.8550584
## [2,] -0.7623155 0.5185316
Une liste est une collection ordonnée d’objets qui peuvent être de classes différentes. Les listes sont en particulier utilisées par certaines fonctions pour renvoyer des résultats complexes sous forme d’un seul objet. On utilise la fonction list(nom1=el1,nom2=el2,…)pour générer une liste. On peut accéder à chaque élément de la liste à l’aide de son index entre double crochets [[…]], ou par son nom précédé du signe $.
x = list("xyz",1:8);x
## [[1]]
## [1] "xyz"
##
## [[2]]
## [1] 1 2 3 4 5 6 7 8
x[[1]];x[[2]]+10
## [1] "xyz"
## [1] 11 12 13 14 15 16 17 18
y = list(matrice=D,vecteur=f,texte="xyz",scalaire=8)
names(y);y[[1]]
## [1] "matrice" "vecteur" "texte" "scalaire"
## [,1] [,2] [,3] [,4]
## [1,] 0.68474178 0.478810205 0.7672717 0.128571704
## [2,] 0.70804500 0.942519202 0.4186286 0.048031351
## [3,] 0.01013511 0.126746896 0.3685384 0.734760914
## [4,] 0.71157042 0.008980543 0.5851269 0.001652146
y$matrice;y$vec
## [,1] [,2] [,3] [,4]
## [1,] 0.68474178 0.478810205 0.7672717 0.128571704
## [2,] 0.70804500 0.942519202 0.4186286 0.048031351
## [3,] 0.01013511 0.126746896 0.3685384 0.734760914
## [4,] 0.71157042 0.008980543 0.5851269 0.001652146
## a1 a2 a3 a4
## 12 22 32 41
y[c("texte","scal")]
## $texte
## [1] "xyz"
##
## $<NA>
## NULL
y[c("texte","scalaire")]
## $texte
## [1] "xyz"
##
## $scalaire
## [1] 8
length(y)
## [1] 4
length(y$vecteur)
## [1] 4
cos(y$scalaire)+y[[2]][1]
## a1
## 11.8545
summary(y)
## Length Class Mode
## matrice 16 -none- numeric
## vecteur 4 -none- numeric
## texte 1 -none- character
## scalaire 1 -none- numeric
Un data frame est analogue à une matrice dont les colonnes peuvent être hétérogènes. Un tableau de données est un ensemble de vecteurs rangés colonne par colonne, chaque colonne correspondant à une variable, chaque ligne à un individu. En particulier, lors d’études statistiques, les données à étudier sont souvent représentées par un data frame sous R. Pour créer un tableau de données, on peut regrouper des variables de même longueur à l’aide de la commande data.frame(nom1=var1,nom2=var2,…). On peut aussi transformer une matrice en un tableau de données en utilisant la commande as.data.frame(mat).
taille = runif(12,150,180)
masse = runif(12,50,90)
sexe = rep(c("M","F","F","M"),3)
H = data.frame(taille,masse,sexe)
H;summary(H)
## taille masse sexe
## 1 158.0637 81.94786 M
## 2 155.9371 62.42993 F
## 3 160.1714 86.81853 F
## 4 174.1804 75.72348 M
## 5 173.8159 74.59815 M
## 6 171.4722 88.50888 F
## 7 154.0794 78.09507 F
## 8 150.2602 72.16378 M
## 9 170.0977 72.20552 M
## 10 155.3758 50.30676 F
## 11 179.7021 57.83264 F
## 12 155.9763 63.02626 M
## taille masse sexe
## Min. :150.3 Min. :50.31 F:6
## 1st Qu.:155.8 1st Qu.:62.88 M:6
## Median :159.1 Median :73.40
## Mean :163.3 Mean :71.97
## 3rd Qu.:172.1 3rd Qu.:79.06
## Max. :179.7 Max. :88.51
H[1,];H$taille;H$sexe
## taille masse sexe
## 1 158.0637 81.94786 M
## [1] 158.0637 155.9371 160.1714 174.1804 173.8159 171.4722 154.0794
## [8] 150.2602 170.0977 155.3758 179.7021 155.9763
## [1] M F F M M F F M M F F M
## Levels: F M
Opérations sur les dataframes
data1= data.frame(x1=1,x2=1:10,a=letters[1:10])
#Par défaut les lignes sont numérotées 1,2 etc.
data1
## x1 x2 a
## 1 1 1 a
## 2 1 2 b
## 3 1 3 c
## 4 1 4 d
## 5 1 5 e
## 6 1 6 f
## 7 1 7 g
## 8 1 8 h
## 9 1 9 i
## 10 1 10 j
names(data1)
## [1] "x1" "x2" "a"
names(data1)<-c("c1","c2","c3")
head(data1,3)
## c1 c2 c3
## 1 1 1 a
## 2 1 2 b
## 3 1 3 c
dim( data1)
## [1] 10 3
row.names(data1)<-letters[1:10]
# le vecteur letters contient les lettres de l'alphabet
head(data1,2)
## c1 c2 c3
## a 1 1 a
## b 1 2 b
Les opérations entre des dataframes sont des opérations terme à terme comme pour les matrices.
A = data.frame(x=1:3,y=2:4)
B = data.frame(xx=1,yy=1:3)
C= data.frame(x=1:3,y=rep("a",3))
A
## x y
## 1 1 2
## 2 2 3
## 3 3 4
B
## xx yy
## 1 1 1
## 2 1 2
## 3 1 3
A+B
## x y
## 1 2 3
## 2 3 5
## 3 4 7
C
## x y
## 1 1 a
## 2 2 a
## 3 3 a
#Pour extraire un élément ou un bloc, la syntaxe est la même
A$x
## [1] 1 2 3
A[ ,1]
## [1] 1 2 3
#Pour concaténer des dataframes ayant le même nombre de lignes
data.frame (A,B)
## x y xx yy
## 1 1 2 1 1
## 2 2 3 1 2
## 3 3 4 1 3
L’unité de base dans R est le vecteur. Les opérations sur les vecteurs sont effectuées élément par élément :
c(1, 2, 3) + c(4, 5, 6)
## [1] 5 7 9
1:3 * 4:6
## [1] 4 10 18
Si les vecteurs impliqués dans une expression arithmétique ne sont pas de la même longueur, les plus courts sont recyclés de façon à correspondre au plus long vecteur. Cette règle est particulièrement apparente avec les vecteurs de longueur 1 :
1:10 + 2
## [1] 3 4 5 6 7 8 9 10 11 12
1:10 + rep(2, 10)
## [1] 3 4 5 6 7 8 9 10 11 12
Si la longueur du plus long vecteur est un multiple de celle du ou des autres vecteurs, ces derniers sont recyclés un nombre entier de fois :
1:10 + 1:5 + c(2, 4) # vecteurs recyclés 2 et 5 fois
## [1] 4 8 8 12 12 11 11 15 15 19
1:10 + rep(1:5, 2) + rep(c(2, 4), 5) # équivalent
## [1] 4 8 8 12 12 11 11 15 15 19
Sinon, le plus court vecteur est recyclé un nombre fractionnaire de fois, mais comme ce résultat est rarement souhaité et provient généralement d’une erreur de programmation, un avertissement est affiché :
1:10 + c(2, 4, 6)
## [1] 3 6 9 6 9 12 9 12 15 12
Grâce à la propriété d’opération élément par élément de R, il devrait être possible — en fait, il est souhaitable — de résoudre le problème sans avoir recours à des boucles.
Le tableau suivant présente les opérateurs mathématiques et logiques les plus fréquemment employés, en ordre décroissant de priorité des opérations. Le tableau contient également les opérateurs d’assignation et d’extraction pré- sentés au chapitre précédent ; il est utile de connaître leur niveau de priorité dans les expressions R. Les opérateurs de puissance (^) et d’assignation à gauche (<-, <<-) sont évalués de droite à gauche ; tous les autres de gauche à droite. Ainsi, 2^
2^
3 est 2^
8, et non 4^
3, alors que 1 - 1 - 1 vaut -1, et non 1.
Principaux opérateurs du langage R, en ordre décroissant de priorité
Opérateurs | Fonctions |
---|---|
$ | extraction d’une liste |
^ | puissance |
- | changement de signe |
: | génération de suites |
%*% %% %/% | produit matriciel, modulo, division entière |
’*’ / | multiplication, division |
+ - | addition, soustraction |
< <= == >= > != | plus petit, plus petit ou égal, égal, plus grand ou égal, plus grand, différent de |
! | négation logique |
& && | « et » logique |
|, || | « ou » logique |
-> ->> | assignation |
<- <<- | assignation |
Les opérateurs du tableau 2 ne sont que des raccourcis utiles pour accéder aux fonctions les plus courantes de R. Pour toutes les autres, il faut appeler la fonction directement. Nous allons dans cette partie passer en revue les règles d’appels d’une fonction et la façon de spécifier les arguments, qu’il s’agisse d’une fonction interne de R ou d’une fonction personnelle :
Par exemple, la définition de la fonction matrix est la suivante:
matrix(data = NA, nrow = 1, ncol = 1, byrow = FALSE, dimnames = NULL)
matrix() compte cinq argument: data, nrow, ncol, byrow et dimanmes. Ici chaque argument a une valeur par défaut (ce n’est pas toujours le cas). Ainsi, un appel de la fonction matrix()sans argument produira une matrice de dimension 1x1 rempli de l’objet NA et dont les dimensions sont sans étiquette.
Le langage R compte un très grand nombre (des milliers !) de fonctions internes. Nous présentons ici les fonctions de base les plus souvent utilisées pour programmer en R et pour manipuler des données.
Manipuler des vecteurs
Manipulation de vecteurs
Nom | Fonction | Exemple |
---|---|---|
seq | génération de suites de nombres | seq(1, 9, by = 2) |
seq_len | version plus rapide de seq | seq_len(10) |
rep | répétition de valeurs ou de vecteurs | rep(2, 10) |
sort | tri en ordre croissant ou décroissant | sort(c(4, -1, 2, 6)) |
rank | rang des éléments (ordre croissant ou décroissant) | rank(c(4, -1, 2, 6)) |
order | ordre d’extraction des éléments | order(c(4, -1, 2, 6)) |
rev | renverser un vecteur | rev(1:10) |
head | extraction ou suppression des n premiers éléments | head(1:10, 3); head(1:10, -3) |
tail | extraction ou suppression des n derniers éléments | tail(1:10, 3); tail(1:10, -3) |
unique | extraction des éléments différents d’un vecteur | unique(c(2, 4, 2, 5, 9, 5, 0)) |
Les exemples des fonctions suivantes utilisent x | x=c(4,-1,2,-3,6) | |
which | positions des valeurs TRUE dans un vecteur booléen | which(x < 0) |
which.min | position du minimum dans un vecteur | which.min(x) |
which.max | position du maximum dans un vecteur | which.max(x) |
match | position de la première occurrence d’un élément | match(2, x) |
%in% | appartenance d’une ou plusieurs valeurs à un vecteur | -1:2 %in% x |
Arrondi
Il existe plusieurs fonctions d’arrondi:
x=c(-3.6800000,-0.6666667, 3.1415927,0.3333333, 2.5200000)
round(x)#arrondi à un nombre défini de décimales (par défaut 0)
## [1] -4 -1 3 0 3
floor(x)#plus grand entier inférieur ou égal à l’argument
## [1] -4 -1 3 0 2
ceiling(x)#plus petit entier supérieur ou égal à l’argument
## [1] -3 0 4 1 3
trunc(x)#troncature vers zéro ; différent de floor pour les nombres négatifs
## [1] -3 0 3 0 2
Résumés statistiques
Le tableau suivant présente quelques fonctions pour les statistiques descriptives:
Résumés statistiques
Nom | Fonction | Exemple |
---|---|---|
sum, prod | somme et produit des éléments d’un vecteur | sum(x); prod(x) |
diff | différences entre les éléments d’un vecteur | diff(x) |
mean | moyenne arithmétique (tronquée avec l’argument trim) | mean(x) |
var, sd | variance et écart type | var(x), sd(x) |
min, max | minimum et maximum d’un vecteur | min(x); max(x) |
range | vecteur contenant le min et le max d’un vecteur | range(x) |
median | médiane empirique | median(x) |
quantile | quantiles empiriques | quantile(x) |
summary | statistiques descriptives d’un échantillon | summary(x) |
R dispose d’un package de base dédié aux statitistique (stats), qui est chargé par défaut. Il permet entre autre d’utiliser les lois statistiques telles que les lois bêta, binomiale, de Cauchy, \(\chi^2\), exponentielle, F de Fisher, gamma, géométrique, hypergéométrique, lognormale, multinomiale, binomiale négative, normale, de Poisson, t de Student, uniforme, de Weibull, etc. Pour chacune de ces lois, R fournit, lorsqu’elle est définie, la densité de probabilité, la fonction de répartition (probabilités cumulées), la fonction de probabilité inverse (quantiles) et un générateur de nombres aléatoires suivant cette loi. Les noms des fonctions sont déterminés de manière systématique.
Loi Normale
Loi Normale
Les arguments des fonctions dépendent des paramètres des lois.
Une loi normale admet deux paramètres : l’espérance (ou moyenne, mean) \(\mu\) (mu) et l’écart type (standard deviation) \(\sigma\) (sigma). Les fonctions associées à la loi normale sont donc les suivantes :
Nom des fonctions liées aux lois de probabilité
Loi..suffixe | Densité.de.probabilité | Fonction.de.répartition | Quantiles | Générateur.aléatoire |
---|---|---|---|---|
d | p | q | r | |
bêta, beta | dbeta | pbeta | qbeta | rbeta |
binomiale, binom | dbinom | pbinom | qbinom | rbinom |
de Cauchy, cauchy | dcauchy | pcauchy | qcauchy | rcauchy |
Chi2, chisq | dchisq | pchisq | qchisq | rchisq |
exponentielle, exp | dexp | pexp | qexp | rexp |
F, f | df | pf | qf | rf |
gamma, gamma | dgamma | pgamma | qgamma | rgamma |
géométrique, geom | dgeom | pgeom | qgeom | rgeom |
hypergéométrique, hyper | dhyper | phyper | qhyper | rhyper |
log-normale, lnorm | dlnorm | plnorm | qlnorm | rlnorm |
multinomiale, multinorm | dmultinorm | pmultinorm | qmultinorm | rmultinorm |
binomiale négative, nbinom | dnbinom | pnbinom | qnbinom | rnbinom |
normale, norm | dnorm | pnorm | qnorm | rnorm |
de Poisson, pois | dpois | ppois | qpois | rpois |
t de Student, t | dt | pt | qt | rt |
uniforme, unif | dunif | punif | qunif | runif |
de Weibull, weibull | dweibull | pweibull | qweibull | rweibull |
Loi Uniforme
Une loi uniforme admet deux paramètres : le minimum a et le maximum b de l’intervalle de définition. Nous avons donc :
- dunif(x) : densité de probabilité en x de la uniforme sur [0 ; 1] ;
- dunif(x, a, b) ou dunif(x, min = a, max = b) : densité de probabilité en x de la loi uniforme sur [a ; b]
Loi Binomiale
Une loi binomiale admet deux paramètres : la taille de l’échantillon (size, nombre de tirages) n et la probabilité de réussite de chaque épreuve, P. Nous avons donc :
- dbinom(k, n, P) ou dbinom(k, size = n, prob = P) : probabilité d’avoir k réussites parmi n tirages
Loi Exponentielle
Une loi exponentielle admet un paramètre : le taux (rate) \(\lambda\) (lambda). Nous avons donc :
- dpois(k, l) ou dpois(k, lambda = l) : densité de probabilité en k de la loi de Poisson de paramètre l
L’une des grandes forces de R est la possibilité pour l’utilisateur de définir facilement et rapidement de nouvelles fonctions. Les fonctions personnelles définies dans l’espace de travail ou dans un package sont traitées par le système exactement comme les fonctions internes. Vous devriez envisager d’écrire une fonction chaque fois que vous avez copié et collé un bloc de code plus de deux fois (c’est-à-dire que vous avez maintenant trois copies du même code). Par exemple, examinez le code suivant :
df = data.frame(
a = rnorm(10),
b = rnorm(10),
c = rnorm(10),
d = rnorm(10)
)
df$a <- (df$a - min(df$a, na.rm = TRUE)) /
(max(df$a, na.rm = TRUE) - min(df$a, na.rm = TRUE))
df$b <- (df$b - min(df$b, na.rm = TRUE)) /
(max(df$b, na.rm = TRUE) - min(df$a, na.rm = TRUE))
df$c <- (df$c - min(df$c, na.rm = TRUE)) /
(max(df$c, na.rm = TRUE) - min(df$c, na.rm = TRUE))
df$d <- (df$d - min(df$d, na.rm = TRUE)) /
(max(df$d, na.rm = TRUE) - min(df$d, na.rm = TRUE))
A ce stade, vous devriez être capable de déchifrer ce code et comprendre que je cherche à redimensionner les variables entre 0 et 1. Mais avez-vous repéré l’erreur? J’ai fait une erreur en copiant-et-collant le code pour df$b: J’ai oublié de changer un a en un b. Extraire le code répété dans une fonction est une bonne idée car il vous empêche de faire ce type d’erreur. Pour écrire une fonction, vous devez d’abord analyser le code. Combien y a-t-il d’entrées?
(df$a - min(df$a, na.rm = TRUE)) /
(max(df$a, na.rm = TRUE) - min(df$a, na.rm = TRUE))
Ce code n’a qu’une seule entrée: df$a. Pour rendre les entrées plus claires, il convient de réécrire le code en utilisant des variables temporaires avec des noms généraux. Ici, ce code ne nécessite qu’un seul vecteur numérique, donc je vais appeler x:
x <- df$a
(x - min(x, na.rm = TRUE)) / (max(x, na.rm = TRUE) - min(x, na.rm = TRUE))
#> [1] 0.289 0.751 0.000 0.678 0.853 1.000 0.172 0.611 0.612 0.601
Le code refait un même calcul plusieurs fois. Nous calculons l’étendue (max-min) des données trois fois, mais il est logique de le faire en une seule étape:
rng <- range(x, na.rm = TRUE)
(x - rng[1]) / (rng[2] - rng[1])
#> [1] 0.289 0.751 0.000 0.678 0.853 1.000 0.172 0.611 0.612 0.601
Maintenant que nous avons simplifié le code et vérifié qu’il fonctionne correctement, nous pouvons le transformer en une fonction :
rescale01 <- function(x) {
rng <- range(x, na.rm = TRUE)
(x - rng[1]) / (rng[2] - rng[1])
}
rescale01(c(0, 5, 10))
## [1] 0.0 0.5 1.0
Trois étapes clés pour créer une nouvelle fonction10 Un sondage aléatoire simpe consiste à dresser une liste exhaustive de toutes les unités de la population étudiée (base de sondage) et à procéder à un tirage au sort à l’aide par exemple d’une table de nombres au hasard. Avec cette procédure, toutes les unités de sondage ont la même probabilité d’appartenir à l’échantillon.:
Choisissez un nom pour la fonction (dans l’exemple nous avons utilisé rescale01 parce que cette fonction change l’échelle des valeurs entre 0 et 1.
Déclarez les entrées, ou les arguments, de la fonction à l’intérieur de la fonction (dans l’exemple nous avons un seul argument. Si nous avions plusieurs l’appel ressemblerait à la fonction (x, y, z)).
Placez le code que vous avez développé dans le corps de la fonction, un bloc {…} qui suit immédiatement la fonction (…).
Notez bien l’ensemble du processus : Nous avons créer la fonction seulement après que nous ayons compris son fonctionnement avec une entrée simple. De plus, Il est important de vérifier le fonctionnement d’un code avant de le transformer en une fonction. À ce stade, il convient de vérifier votre fonction avec quelques entrées différentes:
rescale01(c(-10, 0, 10))
## [1] 0.0 0.5 1.0
rescale01(c(1, 2, 3, NA, 5))
## [1] 0.00 0.25 0.50 NA 1.00
Nous pouvons maintennat simplifier le code de l’exemple original à l’aide de la fonction:
df$a <- rescale01(df$a)
df$b <- rescale01(df$b)
df$c <- rescale01(df$c)
df$d <- rescale01(df$d)
Un autre avantage des fonctions est que si nos besoins changent, nous avons à faire le changement en un seul endroit. Par exemple, nous pouvons découvrir que certaines de nos variables incluent des valeurs infinies, et donc rescale01 () échoue:
x <- c(1:10, Inf)
rescale01(x)
## [1] 0 0 0 0 0 0 0 0 0 0 NaN
Parce que nous avons extrait le code dans une fonction, nous avons seulement besoin de faire le correctif en un seul endroit:
rescale01 <- function(x) {
rng <- range(x, na.rm = TRUE, finite = TRUE)
(x - rng[1]) / (rng[2] - rng[1])
}
rescale01(x)
## [1] 0.0000000 0.1111111 0.2222222 0.3333333 0.4444444 0.5555556 0.6666667
## [8] 0.7777778 0.8888889 1.0000000 Inf
Il s’agit d’une partie importante du principe «Ne vous répétez pas» (ou DRY). Plus vous répétez des morceaux de code dans des endroits différents plus la mise à jour de votre code sera compliquée et donc de créer des bugs.
Nous considérons la situation où la prévalence est estimée sur la base d’un sondage aléatoire simple11 if (condition) { # code à exécuter si condition est vraie } else { # code à exécuter si condition est fausse }. Sur l’échantillon de taille n on observe k individus avec le signal étudié (Maladie par exemple). La prévalence est estimé par \(p_{0}=\frac{k}{n}\).
Plutôt que de se contenter de cette estimation \(p_{0}\) de la véritable valeur cherchée \(p\) , on préfère calculer un intervalle dans lequel la vraie valeur p a de grandes chances de se trouver : \[p_{0}\pm\varepsilon_{\alpha}\sqrt{\frac{p_{0} (1-p_{0})}{n}}\]
ic_prev=function(k,n,alpha){
p=k/n
delta=qnorm(1-alpha/2)*sqrt(p*(1-p)/n)
c(p-delta,p+delta)
}
ic_prev(23,100,0.05)
## [1] 0.1475183 0.3124817
Les conditions d’application de cette formule sont: n et n-k soient tous les deux \(\geq\) 5. Nous allons introduire ces conditions dans la fonction. L’exécution du code de calcul de l’intervalle de confiance sera conditionnelle12 Précision absolue :\[\Delta=\varepsilon_{\alpha}\sqrt{\frac{p(1-p)}{n}}\] \[\varepsilon_{\alpha}=qnorm(1-alpha/2)\].
ic_prev=function(k,n,alpha){
if(k<5|n-k<5) {
c("n et n-k doivent être >= 5 ")
}
else {
p=k/n
delta=qnorm(1-alpha/2)*sqrt(p*(1-p)/n)
c(p-delta,p+delta)
}
}
ic_prev(3,100,0.05);ic_prev(96,100,0.05)
## [1] "n et n-k doivent être >= 5 "
## [1] "n et n-k doivent être >= 5 "
ic_prev(30,100,0.05)
## [1] 0.2101832 0.3898168
Le calcul de la taille de l’échantillon nécessite de renseigner le niveau de la prévalence que l’on cherche à estimer et la précision souhaitée13 http://r4ds.had.co.nz/tibbles.html#tibbles-vs.data.frame. A partir de la formule de la précision absolue, il est facile de déduire n en fonction de \(\Delta\), \(p\) et \(\varepsilon_{\alpha}\). \[n=\varepsilon^{2}_{\alpha}\frac{p(1-p)}{\Delta^{2}}\] Cette formule s’applique uniquement lorsque \(\frac{n}{N}\leq 0.10\). Dans le cas contraire un ajustement de la taille de l’échantillon n en fonction N taille de la population est à faire :
\[n^\prime=\frac{1}{\frac{1}{n}+\frac{1}{N}}\]
samplesize_prev=function(p,delta,alpha,N=Inf){
#N=Inf permet d'avoir une entrée par défaut
n=(qnorm(1-alpha/2)^2)*p*(1-p)/(delta^2)
ceiling(ifelse(N==Inf,n,(1/n+1/N)^-1))
#l'opérateur == est un opérateur logique
#différent de = qui assigne une valeur à un objet
}
samplesize_prev(.4,0.1,0.05)
## [1] 93
samplesize_prev(.4,0.1,0.05,500)
## [1] 78
Il ne s’agit pas de faute d’orthographe, tibbles au lieu de tables, mais d’une nouvelle classe d’objet dans R. Un (e) tiblle se comporte exactement comme un(e) data.frame mais leurs options d’impression par défaut sont différenetes14 European Center for Disease Prevention and Control, http://http://ecdc.europa.eu/en/Pages/home.aspx. A partir de cette partie du document, nous allons utilisé un groupe de packages appelé tidyverse. Ce groupe comprend les packages : ggplot2, tibble, tidyr, readr, purrr et dplyr. Si vous exécutez le code library(tidyverse)
et obtenez le message d’erreur “il n’y a pas de paquet appelé ‘tidyverse’”, vous devez d’abord l’installer, puis réexécuter la library(tidyverse)
.
install.packages("tidyverse")
library(tidyverse)
Même si un package est installé dans votre système R, vous devez le recharger à chaque démarrage d’une nouvelle session. Afin de rendre plus explicite la provenance d’une fonction ou d’un objet en général, nous avons la possibilité d’utiliser la forme spéciale suivante : package::function(). Par exemple:
ggplot2::ggplot()
#la fonction ggplot est une fonction du package ggplot2
Pour gérer nos données, nous allons utiliser une grammaire qui repose sur quelques verbes simples:
- select() permet de sélectionner les colonnes d’un jeu de données ;
- filter() permet de filter les lignes en fonction de conditions logiques (par exemple sélectionner les lignes où telle variable est supérieure à telle valeur, etc) ;
- rename() permet de renommer les variables ;
- summarise() permet de résumer ou synthétiser un jeu de données ;
- mutate() permet de définir de nouvelles variables ;
- arrange() permet de trier le tableau de données.
Ces fonctions font partie du package dplyr. Ce dernier contient aussi la fonction group_by qui permet d’exécuter des opérations par sous-groupes du jeu de données.
Le package tidyr vous facilite la mise ne forme de vos données grâce à ses deux principales fonctions:
- gather() pour passer en mode clé-valeur
- spread() pour passer en mode large
Nous prenons comme exemple les données des cas de listériose déclarés en Europe entre 2008 et 201515 N.B. Vous devez écrire nouveau nom = ancien nom. Ce fichier est au format CSV. Pour l’importer, on utilise la fonction read_csv() de la librairie readr.
library(tidyverse)
## Loading tidyverse: ggplot2
## Loading tidyverse: tibble
## Loading tidyverse: tidyr
## Loading tidyverse: readr
## Loading tidyverse: purrr
## Loading tidyverse: dplyr
## Conflicts with tidy packages ----------------------------------------------
## filter(): dplyr, stats
## lag(): dplyr, stats
tbl_list=read_csv("LIST_2008-2015_EU.csv")
## Parsed with column specification:
## cols(
## `Age Group` = col_character(),
## Gender = col_character(),
## Country = col_character(),
## Month = col_integer(),
## Year = col_integer(),
## `Number Of Cases` = col_integer()
## )
tbl_list
## # A tibble: 6,974 × 6
## `Age Group` Gender Country Month Year `Number Of Cases`
## <chr> <chr> <chr> <int> <int> <int>
## 1 00 F Austria 2 2008 1
## 2 00 F Austria 8 2008 1
## 3 00 F Austria 11 2008 1
## 4 19-44 M Austria 7 2008 1
## 5 19-44 F Austria 6 2008 1
## 6 19-44 F Austria 7 2008 1
## 7 45-64 M Austria 5 2008 1
## 8 45-64 M Austria 8 2008 2
## 9 45-64 M Austria 9 2008 1
## 10 45-64 M Austria 10 2008 1
## # ... with 6,964 more rows
Pour afficher un apperçu différent du tableau, vous pouvez utiliser la fonction glimpse(). Pour enchaîner des instructions nous allons utilser un pipe16 Grâce à la fonction kable()du package knitr comme si les données étaient passées dans un tuyau. Les pipes sont représentées par le code %>%.
tbl_list %>%
glimpse()
## Observations: 6,974
## Variables: 6
## $ Age Group <chr> "00", "00", "00", "19-44", "19-44", "19-44", "...
## $ Gender <chr> "F", "F", "F", "M", "F", "F", "M", "M", "M", "...
## $ Country <chr> "Austria", "Austria", "Austria", "Austria", "A...
## $ Month <int> 2, 8, 11, 7, 6, 7, 5, 8, 9, 10, 9, 2, 3, 9, 3,...
## $ Year <int> 2008, 2008, 2008, 2008, 2008, 2008, 2008, 2008...
## $ Number Of Cases <int> 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 2, 1, 2, 2, 1, 1...
Pour un apperçu complet du tableau, utilisez la fonction View()
tbl_list %>%
View()
Vous avez sans doute remarqué que dans un tibble les noms des colonnes ne sont ni tronqués ni modifiés. Cependant, lorsqu’un nom comporte des espaces ou est un nombre il est mis entre deux guillemets: ` `
La fonction filter() permet de filtrer la table en fonction d’une condition logique.
Par exemple, sur la table tbl_list, nous pouvons filtrer la table pour ne garder que les cas de listérioses survenus en France :
tbl_list %>%
filter(Country=="France")
## # A tibble: 755 × 6
## `Age Group` Gender Country Month Year `Number Of Cases`
## <chr> <chr> <chr> <int> <int> <int>
## 1 00 <NA> France 11 2008 1
## 2 00 M France 1 2008 2
## 3 00 M France 9 2008 1
## 4 00 M France 12 2008 1
## 5 00 F France 3 2008 1
## 6 00 F France 5 2008 2
## 7 00 F France 9 2008 1
## 8 00 F France 11 2008 2
## 9 01-03 M France 10 2008 1
## 10 04-10 M France 8 2008 1
## # ... with 745 more rows
Nous pouvons également combiner plusieurs conditions. Dans l’exemple suivant, nous filtrons les cas survenus en France après 2011.
tbl_list %>%
filter(Country=="France",Year>2011)
## # A tibble: 364 × 6
## `Age Group` Gender Country Month Year `Number Of Cases`
## <chr> <chr> <chr> <int> <int> <int>
## 1 11-18 F France 5 2012 1
## 2 11-18 F France 8 2012 2
## 3 11-18 F France 12 2012 1
## 4 19-44 M France 1 2012 1
## 5 19-44 M France 3 2012 1
## 6 19-44 M France 4 2012 1
## 7 19-44 M France 5 2012 1
## 8 19-44 M France 6 2012 1
## 9 19-44 M France 7 2012 2
## 10 19-44 M France 8 2012 1
## # ... with 354 more rows
# "," remplace le symbol &
tbl_list %>%
filter(Country=="France" & Year>2011)
## # A tibble: 364 × 6
## `Age Group` Gender Country Month Year `Number Of Cases`
## <chr> <chr> <chr> <int> <int> <int>
## 1 11-18 F France 5 2012 1
## 2 11-18 F France 8 2012 2
## 3 11-18 F France 12 2012 1
## 4 19-44 M France 1 2012 1
## 5 19-44 M France 3 2012 1
## 6 19-44 M France 4 2012 1
## 7 19-44 M France 5 2012 1
## 8 19-44 M France 6 2012 1
## 9 19-44 M France 7 2012 2
## 10 19-44 M France 8 2012 1
## # ... with 354 more rows
#les deux codes donnent le même résultat
Pour combiner des conditions avec la logique “ou”, vous pouvez utilser le symbol “|”.
La fonction select() est un verbe, qui comme son nom l’indique, permet de sélectionner des variables :
tbl_list %>%
select(`Number Of Cases`,Country,Year)%>%
filter(`Number Of Cases`>20)
## # A tibble: 4 × 3
## `Number Of Cases` Country Year
## <int> <chr> <int>
## 1 21 Germany 2014
## 2 23 Germany 2014
## 3 28 Germany 2015
## 4 21 Germany 2015
# '' permet d'appeler des variables avec des caractères spéciaux
Il est possible de sélectionner plusieurs colonnes contiguës grâce à l’instruction “X:Z” et de na pas afficher certaines variables en les précédent par le signe “-”. ##Trier les données Une autre opération utile consiste à trier le jeu de données, dans l’ordre croissant ou décroissant selon un ou plusieurs critères. Cette opération s’exécute merveilleusement avec la fonction arrage():
tbl_list %>%
arrange(Gender)
## # A tibble: 6,974 × 6
## `Age Group` Gender Country Month Year `Number Of Cases`
## <chr> <chr> <chr> <int> <int> <int>
## 1 00 F Austria 2 2008 1
## 2 00 F Austria 8 2008 1
## 3 00 F Austria 11 2008 1
## 4 19-44 F Austria 6 2008 1
## 5 19-44 F Austria 7 2008 1
## 6 45-64 F Austria 9 2008 2
## 7 65-74 F Austria 3 2008 1
## 8 65-74 F Austria 5 2008 1
## 9 65-74 F Austria 7 2008 2
## 10 65-74 F Austria 9 2008 1
## # ... with 6,964 more rows
# par défaut arrange tri dans l'ordre croissant
tbl_list %>%
arrange(desc(`Number Of Cases`))%>%
#desc(variable) pour un tris décroissant
#(comme decreasing=True de la fonction sort())
select(Country,`Number Of Cases`,Year)
## # A tibble: 6,974 × 3
## Country `Number Of Cases` Year
## <chr> <int> <int>
## 1 Germany 28 2015
## 2 Germany 23 2014
## 3 Germany 21 2014
## 4 Germany 21 2015
## 5 Germany 19 2015
## 6 Germany 18 2013
## 7 Germany 18 2014
## 8 Germany 18 2015
## 9 France 17 2013
## 10 Germany 17 2014
## # ... with 6,964 more rows
Rien n’empêche de multiplier les critères de tri, il suffit de les séparer par des virgules, comme pour select() ou filter().
Summarise() est une fonction dite de “résumé” qui retourne une seule information. Par exemple la moyenne, la variance, l’effectif….
tbl_list %>%
summarise(`Nombre total des cas`=sum(`Number Of Cases`))
## # A tibble: 1 × 1
## `Nombre total des cas`
## <int>
## 1 14929
Le résumé peut être fait par groupe grâce à la fonction group_by
(). Le principe consiste à découper le jeu de données puis réaliser des opérations sur chacun des sous-groupes et ensuite combiner les différenst résultats: split -apply - combine.
Traitements par groupe dans un pipe. Source: THINKR
tbl_list %>%
group_by(Country)%>%
summarise(`Nombre total des cas`=sum(`Number Of Cases`))
## # A tibble: 29 × 2
## Country `Nombre total des cas`
## <chr> <int>
## 1 Austria 296
## 2 Belgium 465
## 3 Croatia 7
## 4 Cyprus 5
## 5 Czech Republic 272
## 6 Denmark 496
## 7 Estonia 36
## 8 Finland 423
## 9 France 2699
## 10 Germany 3597
## # ... with 19 more rows
La fonction names() permet d’afficher les noms des variables.
tbl_list %>%names()
## [1] "Age Group" "Gender" "Country" "Month"
## [5] "Year" "Number Of Cases"
La fonction rename() permet de renommer certaines variable d’un tableau de données. Par exemple vous pouvez renommer la variable Month en mois et Year en année17 La fonction tribble scanne les données d’un tableau où les noms des variables sont précédés par le symbole ~ et séparés par des virgules et les données sont saisies directement avec des séparateurs “,”
tbl_list %>%
rename(mois=Month, `année`=Year)%>%
names()
## [1] "Age Group" "Gender" "Country" "mois"
## [5] "année" "Number Of Cases"
La fonction mutate() permet de définir de nouvelles variables. Par exemple, sur le data.frame indiv, nous avons le poids et la taille des individus. Nous pouvant calculer l’indice corporel à partir de ses deux variables : \[IC = \frac{poids}{taille^{2}}\] Avec le poids en Kg et la taille en mètre. Pour commencer, nous allons transformer le tableau indiv en tibble.
tbl_indiv=as_data_frame(indiv)%>%
select(nomen,cod_com,sexe_ps,region,v2_age,taillem,poids)%>%
rename(ID_indiv=nomen,`code postal`=cod_com,sexe=sexe_ps,age=v2_age,taille=taillem)
tbl_indiv
## # A tibble: 4,079 × 7
## ID_indiv `code postal` sexe region age taille poids
## <int> <int> <fctr> <fctr> <int> <int> <dbl>
## 1 110006 77239 femme Région Parisienne 54 162 82.0
## 2 110007 77239 homme Région Parisienne 70 170 70.0
## 3 110020 78291 femme Région Parisienne 43 170 96.0
## 4 110021 78003 femme Région Parisienne 75 152 53.0
## 5 110025 78003 femme Région Parisienne 39 165 57.0
## 6 110034 91200 femme Région Parisienne 61 152 53.0
## 7 110046 91200 homme Région Parisienne 76 163 66.5
## 8 110057 77143 homme Région Parisienne 52 175 82.0
## 9 110067 75102 homme Région Parisienne 38 181 73.0
## 10 110071 75102 femme Région Parisienne 32 173 58.0
## # ... with 4,069 more rows
Pour créer la nouvelle variable, IC, nous allons utiliser la fonction mutate():
tbl_indiv%>%
mutate(IC=poids/(taille/100)^2)%>%
mutate(IC=round(IC,1))%>%
select(taille,poids,IC)
## # A tibble: 4,079 × 3
## taille poids IC
## <int> <dbl> <dbl>
## 1 162 82.0 31.2
## 2 170 70.0 24.2
## 3 170 96.0 33.2
## 4 152 53.0 22.9
## 5 165 57.0 20.9
## 6 152 53.0 22.9
## 7 163 66.5 25.0
## 8 175 82.0 26.8
## 9 181 73.0 22.3
## 10 173 58.0 19.4
## # ... with 4,069 more rows
Créons un nouveau tbl avec IC et résumons les données:
tbl_indiv2=tbl_indiv%>%
mutate(IC=poids/(taille/100)^2)%>%
mutate(IC=round(IC,1))
tbl_indiv2%>%
summarise(
`age moyen`=mean(age,na.rm=TRUE),
`poids moyen`=mean(poids,na.rm=TRUE),
`taille moyenne`=mean(taille/100,na.rm=TRUE)
)
## # A tibble: 1 × 3
## `age moyen` `poids moyen` `taille moyenne`
## <dbl> <dbl> <dbl>
## 1 33.51312 59.78795 1.598846
Avec la flexibilité sur les noms des variables il devient facile de construire des tableaux directement à partir de R18 The Grammar of Graphics (Statistics and Computing) Springer-Verlag New York, Inc. Secaucus, NJ, USA ©2005 ISBN:0387245448.
Tableau résumant des données de tbl_indiv
age moyen | poids moyen | taille moyenne |
---|---|---|
33.51312 | 59.78795 | 1.598846 |
Traitons maintenant un jeu de données sur la contamination de certains aliments par l’acrylamide. Ce jeu de données est stocké dans le fichier “acrylamide.csv”. Vous allez importer ces données avec la fonction read.csv puis les transformer en tibble grâce à as_data_frame()
.
tbl_acrylamide=as_data_frame(read.csv("acrylamide.csv"))
tbl_acrylamide%>%
names()
## [1] "codal" "lib" "année" "région" "Unité"
## [6] "acrylamide"
Le tableau tb_acrylamide a six colonnes: codal, lib, année, région, Unité et acrylamide. Respectivement, il s’agit du code aliment, son libellé, la région où l’échantillon a été pris, l’unité de la mesure et le résultat de recherche de l’acrylamide dans l’échantillon. Chaque ligne correspond à un échantillon. Nous cherchons à calculer la moyenne des concentrations à partir des données du tibble acrylamide:
tbl_acrylamide
## # A tibble: 192 × 6
## codal lib année région Unité acrylamide
## <fctr> <fctr> <int> <int> <fctr> <fctr>
## 1 92055 sandwich 2007 1 µg/kg 34.2
## 2 92055 sandwich 2008 1 µg/kg NQ
## 3 92055 sandwich 2008 6 µg/kg ND
## 4 92055 sandwich 2009 6 µg/kg NQ
## 5 92055 sandwich 2007 7 µg/kg 20.9
## 6 92055 sandwich 2008 9 µg/kg 36
## 7 92055 sandwich 2008 9 µg/kg NQ
## 8 92055 sandwich 2007 34 µg/kg NQ
## 9 92055 sandwich 2008 34 µg/kg ND
## 10 39230 crème dessert 2007 99 µg/kg ND
## # ... with 182 more rows
Nous constatons que la variable acrylamide est comprise comme facteur. Ceci est du au fait que dans cette colonne certaines concentrations sont codées par NQ ou ND (Non quantifaible ou non détectable). Pour rendre ces données utilisables, nous devons réaliser différentes opération. Nous allons en premier créer une fonction qui attribuera des valeurs à NQ et à ND :
censure=function(x,LOD,LOQ){
y=x
y[y=="NQ"]<-LOQ
y[y=="ND"]<-LOD
y
}
Testez votre nouvelle fonction avec un petit jeu de données.
Maintenant nous allons effectuer différentes opérations connectées par des pipes (%>%) :
- créer une nouvelle variable ci à partir de la variable acrylamide
- formater ci en charactère - appliquer la fonction censure sur ci - transformer ci en une variable continue (double)
- grouper les données par région et codal
- calculer la moyenne pour les différents sous groupes formés par le croisement de codal et région
tbl_ci=tbl_acrylamide%>%
mutate(ci=parse_character(acrylamide))%>%
#créer une nouvelle variable ci à partir de
#acrylamide mais avec un format character et non factor
mutate(ci=censure(ci,LOD=4,LOQ=10) )%>%
#on applique la fonction censure qui remplace ND et NQ
#par LOD et LOQ respectivement
mutate(ci=parse_double(ci))%>%
#transforme ci en format double
group_by(`région`,codal)%>%
summarise(`moyenne ci`=mean(10*ci,na.rm=TRUE),n=sum(table(codal)))
Tableau des moyennes des ci en (mg/Kg) par région et par aliment
région | codal | moyenne ci | n |
---|---|---|---|
1 | 18002 | 211.50 | 2 |
1 | 18004 | 358.00 | 2 |
1 | 18073 | 264.50 | 2 |
1 | 25019 | 100.00 | 2 |
1 | 26030 | 132.50 | 2 |
1 | 4005 | 6249.00 | 2 |
1 | 404 | 6922.00 | 2 |
1 | 92055 | 221.00 | 2 |
2 | 18002 | 188.50 | 2 |
2 | 18073 | 256.00 | 2 |
2 | 25019 | 113.00 | 2 |
2 | 26030 | 100.00 | 2 |
2 | 4005 | 6504.50 | 2 |
2 | 404 | 7013.00 | 2 |
5 | 18073 | 217.50 | 2 |
5 | 25009 | 119.50 | 2 |
5 | 26030 | 101.50 | 2 |
5 | 4005 | 9918.50 | 2 |
5 | 404 | 8961.00 | 2 |
6 | 18002 | 236.50 | 2 |
6 | 18073 | 1333.00 | 2 |
6 | 25413 | 132.00 | 2 |
6 | 26030 | 142.00 | 2 |
6 | 4005 | 5000.00 | 2 |
6 | 404 | 11349.00 | 2 |
6 | 92055 | 70.00 | 2 |
7 | 18002 | 225.00 | 2 |
7 | 18004 | 404.00 | 1 |
7 | 18073 | 942.00 | 2 |
7 | 26030 | 204.00 | 2 |
7 | 36004 | 100.00 | 2 |
7 | 36306 | 281.00 | 2 |
7 | 4005 | 5935.00 | 2 |
7 | 404 | 11555.00 | 2 |
7 | 92055 | 209.00 | 1 |
8 | 18002 | 232.50 | 2 |
8 | 18073 | 1245.00 | 2 |
8 | 25019 | 157.00 | 2 |
8 | 26030 | 100.00 | 2 |
8 | 4005 | 8606.00 | 2 |
8 | 404 | 9818.00 | 2 |
9 | 18002 | 178.50 | 2 |
9 | 18073 | 1239.50 | 2 |
9 | 25009 | 119.50 | 2 |
9 | 25413 | 70.00 | 2 |
9 | 26030 | 117.00 | 2 |
9 | 36306 | 40.00 | 2 |
9 | 4005 | 12969.00 | 2 |
9 | 404 | 11376.00 | 2 |
9 | 92055 | 230.00 | 2 |
34 | 18002 | 251.00 | 2 |
34 | 18073 | 290.00 | 1 |
34 | 25089 | 338.50 | 2 |
34 | 25413 | 78.00 | 2 |
34 | 26030 | 188.50 | 2 |
34 | 4005 | 2745.50 | 2 |
34 | 404 | 9363.00 | 2 |
34 | 92055 | 70.00 | 2 |
99 | 13038 | 40.00 | 2 |
99 | 13108 | 40.00 | 2 |
99 | 20905 | 70.00 | 2 |
99 | 20909 | 40.00 | 2 |
99 | 20911 | 40.00 | 2 |
99 | 23000 | 304.00 | 2 |
99 | 23455 | 179.00 | 2 |
99 | 23499 | 304.00 | 2 |
99 | 23585 | 481.50 | 2 |
99 | 23800 | 232.00 | 2 |
99 | 23909 | 203.00 | 2 |
99 | 23939 | 158.00 | 3 |
99 | 24000 | 1929.50 | 2 |
99 | 24036 | 2127.50 | 2 |
99 | 24678 | 112.00 | 2 |
99 | 25405 | 273.50 | 2 |
99 | 25516 | 546.00 | 2 |
99 | 31000 | 783.00 | 2 |
99 | 31004 | 625.75 | 4 |
99 | 31005 | 1337.00 | 2 |
99 | 31032 | 461.00 | 1 |
99 | 32001 | 96.50 | 2 |
99 | 32004 | 119.50 | 2 |
99 | 32121 | 279.50 | 2 |
99 | 38105 | 6975.50 | 2 |
99 | 39206 | 294.00 | 2 |
99 | 39208 | 100.00 | 2 |
99 | 39230 | 40.00 | 2 |
99 | 7004 | 354.50 | 2 |
99 | 7100 | 307.00 | 2 |
99 | 7110 | 383.00 | 2 |
99 | 7160 | 108.00 | 2 |
99 | 7200 | 219.50 | 2 |
99 | 7255 | 447.00 | 2 |
99 | 7300 | 605.00 | 2 |
99 | 7601 | 210.50 | 2 |
99 | 7730 | 263.50 | 2 |
99 | 7741 | 191.50 | 2 |
99 | NR | 231.00 | 1 |
Pour simplifier les calculs, nous allons ignorer la variable région. Nous considérons donc que dans les différentes régions les aliments sont préparés de la même manière.
tbl_ci=tbl_acrylamide%>%
mutate(ci=parse_character(acrylamide))%>%
#créer une nouvelle variable ci à partir de
#acrylamide mais avec un format character et non factor
mutate(ci=censure(ci,LOD=4,LOQ=10) )%>%
#on applique la fonction censure qui remplace ND et NQ
#par LOD et LOQ respectivement
mutate(ci=parse_double(ci))%>%
#transforme ci en format double
group_by(codal)%>%
summarise(`moyenne ci`=mean(10*ci,na.rm=TRUE),n=sum(table(codal)))
Pour avoir les libellés des aliments, nous utiliserons la fonction mutate() et match()19 :
tbl_ci=tbl_ci%>%
mutate(Aliment=
tbl_acrylamide$lib[match(codal,tbl_acrylamide$codal)])
Tableau des moyennes des ci en mg/Kg
codal | moyenne ci | n | Aliment |
---|---|---|---|
13038 | 40.00000 | 2 | compote de pomme |
13108 | 40.00000 | 2 | compote de fruits autres que pomme |
18002 | 217.64286 | 14 | boisson au chocolat |
18004 | 373.33333 | 3 | café noir |
18073 | 752.33333 | 15 | café soluble reconstitué prêt à boire |
20905 | 70.00000 | 2 | dessert au soja nature |
20909 | 40.00000 | 2 | dessert au soja aux fruits |
20911 | 40.00000 | 2 | dessert au soja aromatisé au chocolat |
23000 | 304.00000 | 2 | gâteau |
23455 | 179.00000 | 2 | chou, chouquette |
23499 | 304.00000 | 2 | tarte ou tartelette |
23585 | 481.50000 | 2 | gâteau au chocolat |
23800 | 232.00000 | 2 | crêpe ou gaufre |
23909 | 203.00000 | 2 | cake aux fruits confits |
23939 | 158.00000 | 3 | moelleux au chocolat |
24000 | 1929.50000 | 2 | biscuit sec |
24036 | 2127.50000 | 2 | biscuit sec au chocolat |
24678 | 112.00000 | 2 | barquette à la pulpe de fruit |
25009 | 119.50000 | 4 | hachis parmentier |
25019 | 123.33333 | 6 | pâtes fourrées type ravioli |
25089 | 338.50000 | 2 | cordon bleu de volaille |
25405 | 273.50000 | 2 | quiche lorraine |
25413 | 93.33333 | 6 | hamburger |
25516 | 546.00000 | 2 | pizza |
26030 | 135.68750 | 16 | poisson pané |
31000 | 783.00000 | 2 | barre chocolatée biscuitée |
31004 | 625.75000 | 4 | chocolat au lait |
31005 | 1337.00000 | 2 | chocolat noir |
31032 | 461.00000 | 1 | pâte à tartiner chocolatée |
32001 | 96.50000 | 2 | céréales au chocolat |
32004 | 119.50000 | 2 | muesli |
32121 | 279.50000 | 2 | pétales de maïs |
36004 | 100.00000 | 2 | poulet |
36306 | 160.50000 | 4 | dinde escalope |
38105 | 6975.50000 | 2 | biscuit apéritif |
39206 | 294.00000 | 2 | mousse au chocolat rayon frais |
39208 | 100.00000 | 2 | chocolat viennois ou liégeois |
39230 | 40.00000 | 2 | crème dessert |
4005 | 7240.93750 | 16 | pomme de terre sautée ou frite |
404 | 9544.62500 | 16 | pomme de terre chips salées |
7004 | 354.50000 | 2 | pain grillé |
7100 | 307.00000 | 2 | pain de campagne |
7110 | 383.00000 | 2 | pain complet ou intégral |
7160 | 108.00000 | 2 | baguette |
7200 | 219.50000 | 2 | pain de mie |
7255 | 447.00000 | 2 | pain aux céréales |
7300 | 605.00000 | 2 | biscotte |
7601 | 210.50000 | 2 | croissant |
7730 | 263.50000 | 2 | pain au chocolat |
7741 | 191.50000 | 2 | brioche et pain brioché |
92055 | 154.55556 | 9 | sandwich |
NR | 231.00000 | 1 | gateau moelleux fourré ou non |
R permet de travailler avec plusieurs tables à la fois. Un des principaux intérêts d’une base de données est de pouvoir créer des relations entre les tables, de pouvoir les lier entre elles. Pour le moment, nous n’avons travaillé que sur une seule table à la fois. Dans la pratique, vous aurez certainement plusieurs tables dans votre base, dont la plupart seront interconnectées. Cela vous permettra de mieux découper vos informations, d’éviter des répétitions et de rendre ainsi vos données plus faciles à gérer.
Prenons un exemple simple où nous disposons de deux tables x et y, que nous allons saisir directement grâce à la fonction tribble()20. Ces deux tables sont interconnectées grâce à la variable key.
x <- tribble(
~key, ~val_x,
1, "x1",
2, "x2",
3, "x3"
)
y <- tribble(
~key, ~val_y,
1, "y1",
2, "y2",
4, "y3"
)
Si pour une valeur quelconque de y (par exemple y2) vous souhaitez obtenir sa correpondant dans le tableau x, vous auriez à faire une opération dite jointure.
Il existe plusieurs types de jointures, qui nous permettent de choisir exactement les données que l’on veut récupérer. Les plus importantes sont :
les jointures internes (inner) : elles ne sélectionnent que les données qui ont une correspondance entre les deux tables ;
les jointures externes (outer) : elles sélectionnent toutes les données, même si certaines n’ont pas de correspondance dans l’autre table.
La jointure interne entre x et y :
x%>%
inner_join(y,by="key")
## # A tibble: 2 × 3
## key val_x val_y
## <dbl> <chr> <chr>
## 1 1 x1 y1
## 2 2 x2 y2
La jointure externe peut être faite de trois façons différentes : gauche, droite ou totale. La figure suivante illustre les jointures externes.
Les différentes jointures externes
left_join(x,y,by="key");right_join(x,y,by="key");full_join(x,y,by="key")
## # A tibble: 3 × 3
## key val_x val_y
## <dbl> <chr> <chr>
## 1 1 x1 y1
## 2 2 x2 y2
## 3 3 x3 <NA>
## # A tibble: 3 × 3
## key val_x val_y
## <dbl> <chr> <chr>
## 1 1 x1 y1
## 2 2 x2 y2
## 3 4 <NA> y3
## # A tibble: 4 × 3
## key val_x val_y
## <dbl> <chr> <chr>
## 1 1 x1 y1
## 2 2 x2 y2
## 3 3 x3 <NA>
## 4 4 <NA> y3
Nous cherchons à estimer l’exposition alimentaire à l’acrylamide. Le calcul d’exposition alimentaire à l’acrylamide (pour un individu j) est en général calculé selon la formule suivante:
\[E_{j}=\frac{\sum_{i=1}^{a}C_{i} Q_{ij}}{poids_{j}}\]
Où \(C_{i}\) est la concentration moyenne du contaminant(mg/kg) dans l’aliment i (i est l’indice des différents aliments) et \(Q_{ij}\) la quantité moyenne (en g) consommé par l’individu j de l’aliment i. La somme (\(\sum\)) est faite sur tous les aliments concernés (le nombre d’aliments est noté par a).
Les données nécessaires à ce calcul sont éclatées dans trois tableaux différents : tbl_indiv
, tbl_ci
et tbl_conso
. Nous allons importer ensemble la troisième table. Elle renseigne les caractéristiques des individus interrogés sur leur consommation alimentaire. Vous avez remarqué sans doute l’existence d’une variable nommée au départ nomen que nous avons renommé en ID_indiv
. Cette variable est un identifiant unique de chaque partcipant de l’étude. ID_indiv
nous permettra de faire le lien entre certaines tables.
Nous allons maintenant importer la table “conso.csv”. Puis nous la transformons en tibble :
tbl_conso=as_data_frame(read.csv("consos.csv"))
tbl_conso%>%
names()
## [1] "nomen" "lib" "codgr" "sougr" "codal" "quantité"
tbl_conso=tbl_conso%>%
rename(ID_indiv=nomen)
tbl_conso%>%
names()
## [1] "ID_indiv" "lib" "codgr" "sougr" "codal" "quantité"
La variable nomen correspond à la variable ID_indiv
le tibble tbl_indiv
. La colonne lib donne le libellé de chaque aliment consommé durant la période de l’enquête. Les colonnes cdgr, et sougr donnent des codes uniques pour le groupe d’aliment, le sous groupe d’aliment auquel l’aliment appartient. La colonne codal est un code de l’aliment. La colonne quantité renseigne la quantité moyenne consommée par aliment (en g).
Exercice : calculez l’exposition à l’acrylamide à partir de ces trois tableaux .
ggplot2 est package qui vous permettra de construire, pas à pas (ou par couches), des visualisations des plus simplistes aux plus perfectionnées. la construction de ce package a été fondée sur la grammaire de graphique de Leland Wilkinson21.
Le principe de ggplot2 est de construire le graphique par « couche ». Il existe cinq grandes familles de couches, que nous allons explorer pas à pas.
La première ligne d’un code ggplot2, la première couche, indique à la fonction ggplot() les données de base sur lesquelles s’appuieront toutes les couches suivantes. Les données doivent être organisées dans un data frame ou un tibble. Afin d’explorer le principe de fonctionnement de ggplot, créeons un data frame grâce aux fonctions de base de R:
x1=rnorm(100,50,5); y1=x1+rnorm(100,0,0.7)
x2=rnorm(150,60,7); y2=x2*0.8+rnorm(150,0,1)
x3=rnorm(200,40,4); y3=x3*1.2+rnorm(200,0,1.2)
x=c(x1,x2,x3)
y=c(y1,y2,y3)
population=rep(c("A","B","C"),c(100,150,200))
df=tibble(x,y,population)
Couche déclaration des données
ggplot(data=df)
A ce stade le résultat affiche uniquement un cadre vide.
Couche esthétique (aes)
La deuxième couche consiste à indiquer l’esthétique du graphique grâce à la fonction aes():
ggplot(data=df)+
aes(x=x,y=y,colour=population, fill=population)
ggplot, couche data + couche aes
La syntaxe de la fonction aes():
aes(x = X, y = Y, colour = col, fill = fill, size = size)) — les éléments col, fill et size représentent respectivement les variables que vous souhaitez affecter aux couleurs, à la taille ou au remplissage de vos éléments. L’enchaînement des couches se fait en général avec “+”. Avec la couche aes() nous obenons un cadre avec les axes définis dans aes().
Couche géométrie « geom »
Cette couche permet de définir les éléments visuels qui représenteront vos données. C’est à cette étape que vous devrez choisir un geom
(il en existe plus de 40) qui visualisera vos données : barres, points, histogramme… vous avez l’embarras du choix ! Pour commencer, choisissons des points.
ggplot(data=df)+
aes(x=x,y=y,colour=population, fill=population)+
geom_point()
ggplot, couche data + couche aes + couche geom
Nous obtenons maintenant un graphique complet où les points prennent des couleurs différents selon la valeur de la variable population (ici une variable qualitative 1, 2 et 3).
Couche échelle « scale »
Cette couche vous permet de contrôler les paramètres d’affichage de votre visualisation, sur deux niveaux : les axes, et les projections des données. Autrement dit, vous pouvez définir les limites des axes, le format des chiffres utilisés sur ces axes, les couleurs et les échelles des axes…
Par exemple, nous pouvons changer l’échelle de couleur des points, et l’affichage d’éléments des axes :
ggplot(data=df)+
aes(x=x,y=y,colour=population, fill=population)+
geom_point()+
scale_colour_manual(values = c( "#E66A41", "#88878C", "#A2C616"))+
scale_x_continuous(limits = c(20, 60))
ggplot, couche data + couche aes + couche geom + couche scale
scale_x_continuous(name, breaks, labels, limits, trans)
scale_y_continuous(name, breaks, labels, limits, trans)
Les fonctions pour la transformations des axes sont:
Il est possible d’ajouter des graduations log en utilisant la fonction annotation_logticks().
Couche « facet »
Il est possible de visualiser vos graphiques selon différentes facettes. Cette couche vous permet de séparer votre fenêtre en plusieurs visualisations, selon un facteur défini. Par exemple :
ggplot(data=df)+
aes(x=x,y=y,colour=population, fill=population)+
geom_point()+
facet_grid(. ~ population)
ggplot, utilisation d’une facette
Couche thèmes
Cette couche vous permettra de choisir le « design » de vos visualisations. La fonction, qui commence par theme()
, vous permet de personnaliser tous les éléments visuels : titres, tailles des axes, légende, couleur de fond… etc. Les possibilités de personnalisation du thème sont vastes. À noter que ggplot2 vient avec une dizaine de thèmes prédéfinis (9, pour être précis : puis theme_grey(), theme_gray(), theme_bw(), theme_linedraw(), theme_light(), theme_minimal(), theme_classic(), theme_dark(), theme_void()).
Par exemple:
ggplot(data=df)+
aes(x=x,y=y,colour=population, fill=population)+
geom_point()+
facet_grid(. ~ population)+
theme_bw()
ggplot, application d’un thème
La table “croissance” est un jeu de données sur des taux de croissance de Listeria monocytogenes obsservés sur un aliment donnée.
df=readRDS("croissance.rda")
summary(df)
## température taux de croissance souche
## Min. : 5.00 Min. :0.000000 1:55
## 1st Qu.: 8.00 1st Qu.:0.005115 2:55
## Median :20.00 Median :0.035115 3:55
## Mean :21.82 Mean :0.056912 4:55
## 3rd Qu.:35.00 3rd Qu.:0.096767 5:55
## Max. :45.00 Max. :0.214349
Pour un histogramme simple
ggplot(data=df)+
aes(x=`taux de croissance`)+
geom_histogram()+
ylab("Fréquence")+
theme_bw()
## `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.
Histogramme avec ggplot
Le même histogramme peut être décliné en fonction des souches de L. monoytogenes testées.
ggplot(data=df)+
aes(x=`taux de croissance`,coulour=souche,fill=souche)+
geom_histogram()+
ylab("Fréquence")+
scale_x_continuous(breaks = c(0, 0.10,0.20))+
facet_grid(.~souche)
## `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.
Histogramme avec facette
La fonction geom_point
vous permet de représenter les points de coordonnées (x,y). La fonction geom_smooth
ajoute une courbe de tendance (lissage des points).
ggplot(data=df)+
aes(x=`température`,y=`taux de croissance`)+
geom_point(aes(colour = souche))+
geom_smooth()+
theme_bw()
Nuage de points avec lissage
Même graphe mais par souche:
ggplot(data=df)+
aes(x=`température`,y=`taux de croissance`)+
geom_point(aes(colour = souche),size=0.5)+
geom_smooth()+
facet_grid( . ~ souche)+
scale_x_continuous(breaks = c(10,30))+
theme_bw()
Nuage de points avec lissage at facette
Pour tracer un “Boxplot”, il vous suffit d’ajouter geom_boxplot
. Cependant, il faudra s’aasurer que dans la fonction aes() vous avez bien mentionné la variable qualittaive et la variable quantitative. Afin d’éviter la superposition des points, la fonction geom_jitter ajoute un bruit sur les données afin de les différencier sans nuire à la structure des données.
ggplot(df, aes(souche, `taux de croissance`,fill=souche))+
geom_boxplot()+
geom_jitter(position = position_jitter(width = .2),size=.3) +
theme_bw()
Boxplot avec ggplot
Vous pouvez choisir une forme de boîtes grâce à l’option notch=TRUE et même les présenter horizontalement:
ggplot(df, aes(souche, `taux de croissance`,fill=souche))+
geom_boxplot(notch=TRUE)+
geom_jitter(position = position_jitter(width = .2),size=.3) +
coord_flip()+
theme_bw()
Boxplot en notch et inversion des coordonnées
df3=tibble(x=c(rnorm(100,50,10),rnorm(150,60,12),rnorm(200,40,15)),
population=factor(rep(1:3,c(100,150,200))))
ggplot(data=df3)+
aes(x,fill=population)+
geom_histogram(aes(y = ..density..))
## `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.
ggplot(data=df3)+
aes(x,fill=population)+
geom_density(alpha=0.5)+
ylab("densité")
Densité de probabilité
Il est tout à fait possible d’utiliser des équations mathématiques au lieu des chaînes de caractères. Il suffit d’utiliser quote à la place de “” lorsque vous déclarer les labels des axes ou du titre. Pour connaître les options disponibles consulter ?plotmath (aide de plotmath). Voici un exemple de dose réponse : \[P(reponse)=1-\Big[1+\frac{dose}{\beta}\Big]^{-\alpha}\]
alpha=0.5
beta=118
dose=seq(0,6,0.1) # dose en log10
ld=10^dose
p=1-(1+ld/beta)^(-alpha)
dr=tibble(
dose,
`Probabilité d'infection`=p
)
ggplot(dr)+
aes(x=dose,y=`Probabilité d'infection`)+
geom_line()+
labs(
y=quote(1-(1+frac(dose,alpha))^-alpha)
)+
geom_text(x=4, y=0.5, label="beta==118",parse=T,size=5)+
geom_text(x=4, y=0.6, label="alpha==0.5",parse=T,col="red")
Ajouter des symboles mathématiques