• Aucun résultat trouvé

L’opérateur Pipe

Dans le document Notes de cours de R - Version 2 (Page 113-122)

2.4 Manipulation des données

2.4.5 Calculs matriciels

2.4.6.1 L’opérateur Pipe

Avant de commencer à présenter les manipulations de données, il peut être intéressant d’introduire un opérateur : Pipe (%>%). Cet opérateur provient du package {magrittr}.

Avant de présenter cet opérateur en soi, et afin de montrer son utilité, quelques exemples

ne l’utilisant pas sont présentés. Les explications sont issues de celles de Grolemund and Wickham (2018).

Admettons qu’il soit nécessaire d’effectuer plusieurs opérations à la suite, sur un tableau de données. Par exemple, considérons un tableau dont chaque ligne contient les ventes mensuelles (en colonnes, une par mois) des bars du Cours Julien à Marseille (en lignes) et que l’on souhaite réaliser les opérations suivantes :

1. Calculer la moyenne du chiffre d’affaires (CA) à l’année pour chaque bar ; 2. Ordonner les observations par valeurs croissante des moyennes ;

3. Afficher le top 5 des bars avec le plus gros CA.

Nous allons présenter trois manières différentes de procéder, puis nous regarderons la so-lution avec le fameux opérateur pipe dont on tait encore ici l’utilité (quel suspens !).

Première méthode

La première méthode consiste à *sauvegarder un nouvel objet à chaque étape (inutile de tenter d’évaluer le code qui suit, il ne fonctionnera pas : il s’agit d’un exemple totalement fictif) :

top_ca_bars_anuel_1 <- calcul(ca_bars_cours_ju, type = "moyenne") top_ca_bars_anuel_2 <- ordonner(top_ca_bars_anuel_2,

type = "decroissantes", variable = "ca_annuel") top_ca_bars_anuel_3 <- head(top_ca_bars_anuel_2, 5)

Cette manière de faire requière de créer de nombreux objets intermédiaires avant d’arriver au résultat. On peut noter que le nom de ces objets intermédiaires peut ne pas être facile à trouver/comprendre. Toutefois, s’il est possible de trouver des noms sensés, cette méthode peut être adaptée à la situation. On note également que le code devient plus difficile à lire du fait des nombreux noms de variables inintéressantes.

Remarque 2.4.6

Si le tableau initial contient un volume de données importantes, la création des objets intermédiaire n’occupera pas un espace en mémoire important (R gère cela plutôt bien).

Deuxième méthode

La deuxième méthode consiste à écraser l’objet original à chaque étape :

top_ca_bars_anuel_1 <- calcul(ca_bars_cours_ju, type = "moyenne") top_ca_bars_anuel_1 <- ordonner(top_ca_bars_anuel_1,

type = "decroissantes", variable = "ca_annuel") top_ca_bars_anuel_1 <- head(top_ca_bars_anuel_1, 5)

Si cette solution est moins pénible à rédiger que la précédente, on peut noter qu’elle ne facilite toutefois pas le debogage et que le nom de l’objet modifié a été inscrit 5 fois (et vient donc perturber la lecture rapide du code).

Troisième méthode

La troisième méthode, absolument hideuse à mes yeux (celle par laquelle j’ai commencé il y a quelques années, mea culpa), consiste à rédiger une composition de fonction :

top_ca_bars_anuel_1 <-head(

ordonner( calcul(

ca_bars_cours_ju, type = "moyenne"),

type = "decroissantes", variable = "ca_annuel"

),5 )

Non seulement le temps de rédaction de ce type de code peut être long, mais la lecture du code produit est de surcroît ardue : il faut lire de l’intérieur vers l’extérieur, ce qui est d’autant plus difficile que les arguments de chaque fonction sont éloignés du nom de la fonction.

Roulements de tambour : l’opérateur Pipe

L’opérateur permet de réaliser l’opération chaînée de la manière suivante : top_ca_bars_anuel_1

<-ca_bars_cours_ju %>%

calcul(type = "moyenne") %>%

ordonner(type = "decroissantes", variable = "ca_annuel") %>%

head(5)

Le membre à gauche de l’opérateur est donné comme premier argument de la fonction à droite de l’opérateur.

Avec cette solution, la lecture est rapide pour une personne humaine et le débogage est facilité. Attention à veiller à ne pas enchaîner de trop nombreuses opérations qui feraient perdre ces avantages.

Si on souhaite appeler explicitement le membre de gauche, on peut utiliser le point.comme suit :

top_ca_bars_anuel_1 <-ca_bars_cours_ju %>%

calcul(donnes = ., type = "moyenne") %>%

ordonner(donnees = ., type = "decroissantes", variable = "ca_annuel") %>%

head(x = ., 5)

Comme cet opérateur fait partie de l’environnement tidyverse et que la majorité des fonctions admettent en premier argument les données, il n’est pas nécessaire de rajouter le point au premier argument de la fonction à droite de l’opérateur.

Il convient de préciser que si la fonction à droite du Pipe n’admet pas pour premier ar-gument les données, il est nécessaire de préciser l’arar-gument de la fonction qui recevra les données, comme suit :

donnees %>% fonction(premier_argument = "foo", donnees = .)

2.4.6.2 Sélection

Dans la Section 2.4.2, il a été vu que l’accès aux données d’untibble peut se faire à l’aide du système d’indexation ou bien par celui de nommage, en utilisant la fonction [(). Le package dplyr propose une autre manière de procéder pour sélectionner des colonnes, ou pour filtrer les données. Ces méthodes ont le mérite d’être faciles à lire. Reprenons letibble donné en exemple dans la Section 2.4.2.

femmes <- tibble(

height =c(58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68,69, 70, 71, 72),

weight =c(115, 117, 120, 123, 126, 129, 132, 135, 139,142, 146, 150, 154, 159, 164))

La sélection des colonnes se fait en utilisant la fonction select(). On peut noter que le nom des colonnes ne doit pas être entouré de guillemets. Le premier argument correspond au tibble, le second et les suivants à la ou les colonnes désirées. L’odre d’apparition des colonnes correspond à celui fourni à la fonction select().

library(dplyr)

Si le nom d’une colonne ne respecte pas les conventions de nommage, il est possible d’y accéder avecselect()en entourant le nom de la colonne d’accents graves :

tb_2 <- tibble(`Un nom` = 1:3, `Un autre` = LETTERS[1:3])

Il arrive de vouloir extraire une variable par son nom, ce dernier étant le contenu d’une va-riable externe (dans une boucle par exemple). La pratique suivante n’est pas recommandée, car ambigüe :

nom_variable <- "x"

On peut aussi noter, à travers l’exemple suivant, que le résultats obtenu n’est pas nécessai-rement celui attendu (le nom de la colonne et le nom de la variable qui contient la chaîne de caractères sont identiques) :

nom_variable <- "x"

tb_2 <- tibble(nom_variable = c("A","B", "C"), x = 1:3) select(tb_2, nom_variable)

Une solution consiste à faire précéder le nom de la variable qui contient le nom de la (ou les) colonne(s) que l’on souhaite sélectionner :

select(tb_2, !!nom_variable)

Pourretirer une colonne, il suffit de faire précéder le nom de la colonne par le signe moins :

tb <- tibble(x = seq(1,4), y = xˆ2, z = LETTERS[1:4], t = letters[1:4]) select(tb, -x)

## # A tibble : 4 x 3

## y z t

## <dbl > <chr > <chr >

## 1 1 A a

## 2 4 B b

## 3 9 C c

## 4 16 D d

Pour retirer plusieurs colonnes, il suffit de placer les noms de colonnes dans un vecteur à l’aide de la fonction c() et de faire précéder l’appel de cette fonction du signe moins : select(tb, -c(x, z))

ou de manière équivalente, en listant chaque variable à retirer et en les faisant précéder du signe moins :

Pour sélectionner des lignes, la fonction slice() du package {dplyr} attend de recevoir les indices des lignes à extraire :

tb <- tibble(x = seq(1,4), z = LETTERS[1:4], t = letters[1:4]) slice(tb, c(1,3,4))

## # A tibble : 3 x 3

## x z t

## <int > <chr > <chr >

## 1 1 A a

## 2 3 C c

## 3 4 D d

Remarque 2.4.7

La numérotation des lignes a été changée, elle a été recommencée à zéro.

Si la fonction slice() reçoit des entiers négatifs, les lignes dont l’indice est donné par la valeur absolue de ces entiers seront retirées :

tb <- tibble(x = seq(1,4), z = LETTERS[1:4], t = letters[1:4]) slice(tb, -c(1,3,4))

## # A tibble : 1 x 3

## x z t

## <int > <chr > <chr >

## 1 2 B b

2.4.6.3 Filtrage

Le filtrage par masque a été abordé dans la Section 2.4.2. Encore une fois, le package {dplyr} propose une fonction très simple d’emploi pour sélectionner des lignes :filter(). Le premier argument est le nom du tibble, le second et les suivants correspondent aux expressions à évaluer à l’intérieur du tibble. Il est possible de fournir une expression logique complèxe au deuxième argument ou aux suivants. S’il y a plus de deux arguments, une expression logique sera constuite avec les arguments à partir du deuxième, en les liant par un ET logique.

# Les femmes dont la taille vaut exactement 60 pouces

# Les femmes dont la masse vaut plus de 120 libres

# et dont la taille est inférieure ou égale à 62 pouces femmes %>%

filter(weight > 120, height <= 62)

## # A tibble : 2 x 2

## height weight

## <dbl > <dbl >

## 1 61 123

## 2 62 126

# De manière équivalente : femmes %>%

filter(weight > 120 & height <= 62)

## # A tibble : 2 x 2

## height weight

## <dbl > <dbl >

## 1 61 123

## 2 62 126

# Les femmes dont la masse vaut 150 ou 159 livres

# ou dont la taille est égale à 62 pouces femmes %>%

filter(weight %in% c(150,159) | height == 62)

## # A tibble : 3 x 2

## height weight

## <dbl > <dbl >

## 1 62 126

## 2 69 150

## 3 71 159

Dans le document Notes de cours de R - Version 2 (Page 113-122)