Ce cours est visible gratuitement en ligne.

J'ai tout compris !
Effectuez vos études statistiques avec R

Effectuez vos études statistiques avec R

Mis à jour le vendredi 11 juillet 2014
  • Moyenne
Le langage R

Opérations et analyses statistiques sur des vecteurs

Maintenant que vous savez créer et manipuler des vecteurs il est temps de s'amuser un peu avec ses structures de données et de découvrir comment en tirer des informations statistiques ou encore comment pouvoir y appliquer des opérations arithmétiques.

Cette partie permet de se rappeler que R est un langage dédié à des études statistiques. La partie programmation et gestion de données y sera toujours présente mais ce chapitre vous indiquera aussi comment extraire des informations statistiques intéressantes de vos données.

Effectuer des opérations sur des vecteurs

Au début de ce tutoriel vous avez appris à effectuer des opérations élémentaires sur des variables numériques. Vous savez désormais que ce que l'on appelait alors des variables étaient en fait des vecteurs numériques de longueur 1. Vous ne serez donc pas surpris d'apprendre que les opérations arithmétiques que vous connaissez s'appliqueront de manière similaire sur des vecteurs de taille supérieure. Il reste seulement à savoir comment R gère tout ça et c'est le but de cette section.

Tout d'abord, pour l'ensemble de ce chapitre nous allors étudier un même jeu de données. Nous allons voir comment nous pouvons manipuler et extraire des résultats intéressants d'une série de mesures de poids (en kilogrammes) que nous allons générer grace au code ci dessous.

poids <- c(85,78,54,98,66,78,77,62,89,92,76,77,55,68,71,72,99,102,54,66,98,75,82,83,75)

Nous allons maintenant voir comment nous allons pouvoir effectuer des opérations sur cet objet. Imaginons par exemple que vous venez de vous rendre compte que la balance dont vous vous êtes servis pour faire les mesures était mal réglée et qu'il faut rajouter un kilogramme à toutes les mesures. Il faut donc rajouter 1 à tous les éléments de ce vecteur.
Pour cela, il faudrait théoriquement créer un vecteur aussi long que le vecteur poids et contenant la valeur 1 et de l'additionner au vecteur poids. Cela marche effectivement mais il y a une solution plus simple qui fait appel à une fonctionnalité de R qui s'appelle le recyclage.
Si l'on souhaite faire une opération (une addition dans notre cas) entre deux vecteurs, il est alors possible d'utiliser deux vecteurs de longueur différente. R procèdera alors de la manière suivante: il gardera le vecteur le plus long pour y effectuer l'opération et, à partir du vecteur plus court, il créera un vecteur aussi long que le premier en y répétant (recyclant) les éléments déjà existants autant de fois que nécessaire pour obtenir un vecteur aussi long que le premier. R aura donc deux vecteurs de même longueur à sa disposition pour travailler.
L'exemple ci dessous est l'illustration parfaite de ce principe.

> # On rajoute 1 à tous les éléments du vecteur et on met à jour la variable
> poids <- poids + 1
> poids
 [1]  86  79  55  99  67  79  78  63  90  93  77  78  56  69  72  73 100 103  55  67  99  76  83  84  76
>

On vient de rajouter le nombre 1 au vecteur poids et tous les éléments du vecteur ont été affectés. R a donc pris le vecteur le plus court (le nombre 1 est le seul élément d'un vecteur de taille 1) et a répété son seul élément jusqu'à atteindre la même taille que le vecteur poids. Il ajoute alors ce nouveau vecteur au vecteur poids.

Imaginons maintenant que vous vous êtes rendu compte que votre balance est très facétieuse et ne se déréglait en fait qu'une mesure sur deux. En d'autres termes, les mesures d'index impair sont correctes et les mesures d'index pair sont faussées d'un kilogramme. Comme nous avons déjà rajouté un kilogramme à toutes les valeurs, il va falloir désormais en enlever un à toutes les mesures d'index impair auxquelles il n'aurait rien fallu rajouter précédemment.
En utilisant le recyclage, cette opération peut être faite très simplement de la manière suivante.

> poids <- poids - c(1,0)
Warning message:
In poids - c(1, 0) :
  la taille d'un objet plus long n'est pas multiple de la taille d'un objet plus court
> poids
 [1]  85  79  54  99  66  79  77  63  89  93  76  78  55  69  71  73  99 103  54  67  98  76  82  84  75
>

Ici, R aura alors pris le vecteur le plus petit et l'aura répété autant de fois que nécessaire pour créer un vecteur aussi long que le vecteur poids. Il aura alors soustrait ce nouveau vecteur au vecteur poids. Les éléments d'index impair se seront vus soustrait le premier élément du vecteur (1) tandis que les éléments d'index pairs se seront vus soustraits la valeur 0.

Le tableau ci dessous illustre le fonctionnement de ce principe de recyclage. Pour des soucis de lisibilité, seuls les cinq premiers éléments sont affichés.

Vecteur poids initial

86

79

55

99

67

Vecteur recyclé créé

1

0

1

0

1

Résultat de la soustraction

85

79

54

99

66

Une fois que vous avez compris ce principe de recyclage vous pouvez alors effectuer sans soucis toutes les opérations élémentaires (division, multiplication,...) que vous aviez découvertes lors des premiers chapitres. Vous savez maintenant le faire sur un plus grand nombre d'éléments à la fois et de manière plus puissante.

En ce qui concerne les fonctions arithmétiques que nous avons découvertes précédemment vous devez maintenant savoir qu'elles s'appliquent aussi bien sur des vecteurs longs que sur des vecteurs de taille 1 comme les nombres isolés que nous manipulions au début. Ainsi, lorsque vous donniez un vecteur de taille 1 en argument à une fonction arithmétique, celle ci vous revoyait 1 résultat. Si vous lui transmettez un vecteur plus long, la fonction vous renverra autant de réponses qu'il y a d'éléments dans le vecteur initial. Le code ci dessous en donne l'exemple en transmettant le vecteur poids à la fonction sqrt() (racine carrée).

> sqrt(poids)
 [1]  9.219544  8.888194  7.348469  9.949874  8.124038  8.888194  8.774964  7.937254  9.433981  9.643651  8.717798  8.831761  7.416198  8.306624  8.426150  8.544004  9.949874 10.148892  7.348469  8.185353  9.899495  8.717798  9.055385
[24]  9.165151  8.660254
>

La fonction sqrt() aura donc pris en argument un vecteur contenant 25 éléments numériques et aura renvoyé un vecteur de 25 éléments comprenant la racine carrée de chacun des éléments du vecteur poids.

Maitrisez vos vecteurs

Avant de passer à des opérations ou analyses plus poussées nous allons continuer à découvrir des fonctions qui vous permettront de manipuler avec encore plus de souplesse les vecteurs.

La première de ces fonctions est la fonction length(). Les anglophones auront rapidement compris qu'elle permet de connaitre la longueur d'un objet (length signifie longueur en anglais). Plutôt que de compter ses éléments à la main, la ligne de code suivante nous indiquera que notre vecteur poids comporte 25 éléments.

> length(poids)
[1] 25

Cette fonction peut se réveler bien plus intéressante qu'il n'y parait, notamment pour l'indexation. Continuons avec notre exemple et imaginons que nous souhaitons maintenant retirer la première mesure de notre vecteur car elle semble être fausse. Il nous faut alors sélectionner tous les éléments, du second au dernier. Ce qui peut être réalisé grace à la ligne de code suivante.

> # On met à jour la variable en y assignant un vecteur contenant seulement les éléments allant de 2 à 25
> poids <- poids[2:length(poids)]
> poids
 [1]  79  54  99  66  79  77  63  89  93  76  78  55  69  71  73  99 103  54  67  98  76  82  84  75
> length(poids)
[1] 24
>

Nous voilà donc avec un nouveau vecteur de seulement 24 éléments dans lequel la première valeur du précédent vecteur a été retirée.

Il existe aussi des fonctions permettant de sélectionner seulement certains éléments d'un vecteur, comme par exemple les fonctions head() et tail(). En anglais head signifie tête et tail veut dire queue. La fonction head() permet donc de sélectionner les 6 premiers éléments d'un vecteur tandis que la fonction tail() ne sélectionnera que les 6 derniers. Un argument facultatif n permet de préciser combien d'éléments nous souhaitons exactement sélectionner (la valeur par défaut étant donc 6).

Cette fonction est assez souvent utilisée pour avoir une vision rapide sur la structure ou le contenu d'un objet. Lorsque vous serez amenés à manipuler des vecteurs ou autres structures plus complexes de très grande taille, il sera alors utile de faire recours à l'une de ces fonctions pour n'afficher qu'une partie des données et ainsi avoir un aperçu de l'objet qu'il va falloir traiter. Mais ces fonctions peuvent aussi servir à facilement indexer un vecteur.
Imaginez par exemple que nous souhaitons maintenant enlever le dernier élément de notre vecteur car nous avons aussi des doutes sur sa précision. Notre vecteur étant maintenant composé de 24 éléments, on peut sélectionner les 23 premiers (longueur totale - 1) afin de ne plus avoir le dernier.

poids <- head(poids, length(poids) - 1)

Triez vos vecteurs

Dans le cadre de vos différentes analyses vous devrez parfois trier vos données. Cette section vous présente trois fonctions qui vous permettent d'effectuer ce type de manipulations.

La fonction sort()

La fonction sort() est la première et certainement la plus simple de toutes. Elle prend un le nom de votre vecteur en argument et renvoie un nouveau vecteur contenant les mêmes éléments mais triés dans l'ordre croissant comme le montre l'exemple qui suit.

>sort(poids)
 [1]  54  54  55  63  66  67  69  71  73  76  76  77  78  79  79  82  84  89  93  98  99  99 103

Si vous souhaitez trier vos éléments de manière décroissante, il vous faudra alors préciser un valeur pour l'argument optionnel decreasing (décroissant en anglais) qui par défaut est défini à FALSE. En donnant la valeur TRUE à cet argument vous pourrez alors trier votre vecteur de manière décroissante comme illustré ci-dessous.

> sort(poids, decreasing=TRUE)
 [1] 103  99  99  98  93  89  84  82  79  79  78  77  76  76  73  71  69  67  66  63  55  54  54

Il est aussi possible de trier des vecteurs contenant des éléments non numériques à l'image des chaînes de caractères ou des éléments logiques.

> # Trier un vecteur contenant des chaînes de caractères
> sort(c("A","C","b","a","B"))
[1] "A" "B" "C" "a" "b"
> 
> # ou des éléments logiques (booléens)
> sort(c(TRUE, FALSE, T, F))
[1] FALSE FALSE  TRUE  TRUE
>
La fonction order()

La fonction order() fonctionne de manière similaire à la fonction sort(), arguments y compris. La seule différence, c'est qu'au lieu de renvoyer les valeurs du vecteur, elle va en renvoyer les index comme l'illustre l'exemple ci dessous.

> order(poids)
 [1]  2 18 12  7  4 19 13 14 15 10 21  6 11  1  5 22 23  8  9 20  3 16 17

Ce résultat indique que l'élément d'index 2 est le plus petit, suivi de l'élément d'index 18,... Enfin, l'élément d'index 17 est le plus grand. En transmettant ce vecteur comme index au vecteur poids on est alors en mesure de trier notre vecteur d'origine.

>poids[order(poids)]
 [1]  54  54  55  63  66  67  69  71  73  76  76  77  78  79  79  82  84  89  93  98  99  99 103
>

Lorsque l'on ne travaille que sur un seul vecteur, cette fonction n'est pas la plus pratique car elle oblige à faire en deux étapes ce que la fonction sort() fait en une seule. Mais si vous imaginez que vous travaillez sur plusieurs vecteurs contenant des données correspondantes pour des éléments de même index, cette fonction vous permettra alors de trier tous vos vecteurs à l'aide du vecteur d'index renvoyé par cette fonction order(). Vous aurez d'ailleurs tout loisir de vous entrainer à ce genre de manipulation dans les chapitres suivants. :)

La fonction rank()

La dernière fonction de tri que nous allons maintenant découvrir est la fonction rank(). Elle ne trie pas réellement le vecteur mais renvoie, pour chacun de ses éléments, son rang au sein de la distribution formée par l'ensemble des éléments du vecteur.

> rank(poids)
 [1] 14.5  1.5 21.5  5.0 14.5 12.0  4.0 18.0 19.0 10.5 13.0  3.0  7.0  8.0  9.0 21.5 23.0  1.5  6.0 20.0 10.5 16.0 17.0

Le résultat indique, par exemple, que la quatrième valeur du vecteur, est la cinquième valeur la plus élevée de l'ensemble du vecteur. Vous aurez certainement remarqué que certaines valeurs ne sont pas entières mais décimales. Par défaut, lorsque la fonction rank() rencontre des éléments de même valeur (et donc de même rang), il leur attribue la moyenne de l'ensemble des rangs que prendraient ces éléments. Si par exemple deux éléments ont la plus petite valeur comme c'est ici le cas, ces éléments occupent à la fois le rang 1 et 2 et la fonction leur attribuera ainsi la moyenne de ses deux rangs, à savoir 1.5.

Si cette approche ne vous convient pas, vous pouvez modifier ce comportement par défaut de la fonction en donnant l'une des valeurs suivantes à l'argument ties.method de la fonction rank() pour définir quelle méthode adopter si plusieurs éléments partagent le même rang:

  • first: l'élément situé en premier dans le vecteur se verra assigné le rang le plus petit, l'élément situé en second recevra le rang le plus petit + 1 et ainsi de suite. Cela implique que tous les rangs seront uniques même en cas d'égalité de certains éléments du vecteur.

  • random: les différents éléments recevront de manière aléatoire l'un des rangs qu'ils occupent. Si deux éléments partagent le premier rang, l'un se verra aléatoirement assigné le rang 1 tandis que l'autre le rang 2. De par le coté aléatoire du processus, le résultat peut donc varier entre deux appels identiques à la fonction. De même que précédemment, tous les rangs renvoyés seront uniques.

  • min: en cas de partage d'un rang par plusieurs éléments du vecteur, la valeur minimale des rangs occupés par ses éléments est renvoyée pour tous les éléments concernés. Les éléments de même rang ont alors tous la même valeur.

  • max: fonctionne de la même manière que min, à l'exception que c'est cette fois ci la valeur maximale des rangs occupés par les éléments considérés qui est renvoyée pour ces éléments.

  • average: il s'agit de la méthode par défaut décrite précédemment.

Maintenant que vous connaissez les détails de fonctionnement de cette fonction, libre à vous de vous entrainer à l'utiliser avec les différents paramètres possibles. :)

Analyser la distribution d'un vecteur

Il est maintenant l'heure de faire enfin des statistiques! Ou plus précisément des mesures statistiques. Nous travaillons depuis le début de ce chapitre sur un vecteur contenant des valeurs numériques correspondant au poids de différents individus. Cette ensemble de valeurs forme ce que l'on appelle une distribution.

Une distribution est définie par différentes mesures comme par exemple la médiane ou la variance. Nous allons maintenant apprendre à définir ces mesures avec R.

Mesurer le centre d'une distribution

Il existe deux méthodes principales pour définir le centre d'une distribution: la moyenne et la médiane.

La moyenne

La moyenne arithmétique d'une distribution équivaut à la somme des éléments d'une distribution divisée par ce même nombre d'éléments. Je suppose que c'est une notion à laquelle vous êtes habitués car vous avez du en calculer bon nombre à l'école. :)
Sous R, la moyenne se calcule à l'aide de la fonction mean() (mean voulant dire moyenne en anglais). Cette fonction prend pour argument un vecteur numérique et en retourne la moyenne.

> mean(poids)
[1] 77.56522

Je profite de cette section pour introduire une autre fonction utile qui vous permettra aussi de calculer une moyenne, la fonction sum() qui renvoie la somme des éléments d'un vecteur numérique donné en argument. Avec les autres fonctions vues précédemment vous pouvez alors aussi calculer la moyenne du vecteur poids de la manière suivante.

> sum(poids) / length(poids)
[1] 77.56522

Hormis être plus long, il n'y a aucune différence avec la méthode précédente. Sauf que vous connaissez désormais une nouvelle fonction. :)

La médiane

La médiane est la valeur qui permet de partager une série numérique ordonnée en deux parties de même nombre d'éléments. On dit aussi généralement qu'il s'agit de la valeur centrale d'une distribution. Si vous prenez par exemple la série 1,2,3,4,5 la médiane sera 3 car il y a autant d'éléments avant qu'après 3. Pour une distribution contenant un nombre pair d'éléments la médiane sera alors la moyenne des deux valeurs les plus centrales. Pour la distribution 1,2,3,4,5,6 la médiane sera la valeur comprise entre 3 et 4 donc 3.5.
La médiane et la moyenne renvoient généralement des valeurs similaires si la distribution suit une loi normale. Cependant la médiane est moins affectée par les valeurs extrêmes. Par exemple les séries 1,2,3,4,5 et 1,2,3,4,100 ont la même médiane mais des moyennes différentes. Selon les données que vous utilisez à la présence d'éventuelles valeurs extrêmes artefactuelles, pensez donc à bien choisir entre moyenne et médiane.

La médiane se calcule grace à la fonction median() comme illustré ci dessous.

> median(poids)
[1] 77

Ces deux fonctions, comme certaines autres prenant comme argument des vecteurs, possèdent un argument facultatif na.rm. Cet argument, dont la valeur par défaut est FALSE, définit le comportement de la fonction vis à vis des éléments de type NA. Ces éléments parasitent généralement les calculs car ils sont renoyés en résultat quel que soit le reste de la distribution. Ainsi si vous souhaitez vous débarasser de ces valeurs pour le calcul, il faudra définir la valeur TRUE pour l'argument na.rm.

> # On créé un vecteur contenant des NA
> poids2 <- c(poids, rep(NA,5))
> median(poids2)
[1] NA
> mean(poids2)
[1] NA
>
> median(poids2, na.rm=T)
[1] 77
> mean(poids2, na.rm=T)
[1] 77.56522

Mesurer la dispersion d'une distribution

Une fois que l'on a défini le centre d'une distribution il reste toujours beaucoup d'informations disponibles nous permettant d'en avoir une vue plus précise. Notamment, comment sont organisées les valeurs par rapport à ce centre. Il existe différentes mesures permettant de définir cette dispersion par rapport à la moyenne ou la médiane telles que la valeur maximale, la valeur minimale, les quantiles, la variance ou encore l'écart type.

Valeurs minimales et maximales

Les valeurs minimales et maximales de la distribution représentent les valeurs les plus extrêmes de la distribution. Elles se calculent à l'aide des fonctions min() et max(). Ces fonctions sont aussi sensibles à la présence de NA au sein de la distribution donc n'hésitez pas à employer leur argument na.rm si besoin.

> min(poids)
[1] 54
> max(poids)
[1] 103
Les quantiles

Les quantiles sont les valeurs permettant de séparer une distribution ordonnée de valeurs en q sous-distributions. On parle alors de q-quantile. Le nombre q peut varier selon vos besoins mais il est par exemple fréquent de se référer aux 4-quantiles aussi appelés quartiles. Les quartiles permettent de diviser une distribution ordonnée en 4 parties égales, chacune de ses sous-distributions contenant essentiellement le même nombre d'éléments.

En R, les quantiles se calculent grace à la fonction quantile() qui, par défaut, définit les 4-quantiles (quartiles).

> quantile(poids)
   0%   25%   50%   75%  100% 
 54.0  68.0  77.0  86.5 103.0

Ce résultat indique par exemple que les 25 premiers pourcents de la distribution sont compris entre les valeurs 54 et 68. On peut aussi voir que 75% des valeurs sont inférieures à 86.5 et donc que 25% sont comprises entre cette même valeur et 103. On retrouve aussi la médiane de notre distribution qui correspond à la valeur qui sépare la distribution en deux sous parties de longueur égale.

La fonction quantile() permet de calculer non seulement les quartiles mais aussi tout q-quantile que l'on souhaite. Il faut pour cela spécifier les valeurs adéquates à l'argument probs. Cet argument est défini par un vecteur contenant une série de valeurs numériques comprises entre 0 et 1. Les quantiles seront alors calculés pour chacune des valeurs données. En parcourant l'aide vous pouvez remarquer que la valeur par défaut est seq(0, 1, 0.25) qui renvoie le vecteur 0.00 0.25 0.50 0.75 1.00. Ces valeurs correspondent donc à celles renvoyées en résultat. En donnant un autre vecteur en définition de cet argument on peut par exemple définir les 10-quantiles (aussi appelés déciles) de la distribution formée par le vecteur poids comme en témoigne le code ci dessou.

> quantile(poids, probs=seq(0,1,0.1))
   0%   10%   20%   30%   40%   50%   60%   70%   80%   90%  100% 
 54.0  56.6  66.4  70.2  75.4  77.0  79.0  82.8  91.4  98.8 103.0

Alors, quel est, parmi notre série de mesures de poids, le pourcentage de valeurs supérieur à 79?

40%! On peut en effet remarquer que la valeur 79 est la limite supérieur du 6ème quantile (60%). Ce qui veut dire que toutes les valeurs lui étant supérieure sont compris dans les 40 derniers pourcents de la distribution (100-60).

summary(), la fonction tout en un

Si vous souhaitez avoir une vision assez précise de votre distribution il est probable que vous ayez recours à plusieurs de ces fonctions pour par exemple connaitre à la fois les quartiles, la moyenne et valeurs extrêmes de celle ci. Motivés par ce constat les développeurs de R ont mis à disposition des utilisateurs la fonction summary() (summary siginifie résumé en anglais). Cette fonction renvoie une série d'informations sur une distribution numérique: la valeur minimale, le premier quartile (25%), la médiane (ou second quartile, 50%), la moyenne, le troisième quartile (75%) et la valeur maximale. Le code ci dessous nous montre ce que renvoie cette fonction appliquée au vecteur poids.

> summary(poids, probs=seq(0,1,0.1))
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
  54.00   68.00   77.00   77.57   86.50  103.00
La variance et l'écart type

La variance et l'écart type sont deux mesures liées (l'écart type étant la racine carrée de la variance) permettant de mesure la dispersion d'une distribution par rapport à la moyenne. La variance que l'on peut vulgariser par la moyenne des carrés moins le carré des moyennes prendra une valeur grande si les éléments de la distribution sont généralement éloignés de la moyenne ou une valeur petite si ces éléments sont au contraire resserrés près de la moyenne. Les fonctions var() et sd() permettent de calculer respectivement la variance et l'écart type comme illustré ci dessous.

> var(poids)
[1] 210.8024
> sd(poids)
[1] 14.51903

Maintenant le vecteurs n'ont presque plus de secrets pour vous! Si vous avez compris les deux précédents chapitres vous avez alors de solides bases pour appréhender le langage R, les vecteurs y occupant une place prépondérante.

Découvrez aussi ce cours en...

Exemple de certificat de réussite
Exemple de certificat de réussite