1 Contexte

En suivant cette fiche, vous utiliserez les mêmes données de ventes fictives du magasin en ligne aux États-Unis que lors de la première séance. Ces données sont téléchargeable sur Kaggle (une plateforme web, filiale de Google, qui permet aux data-scientists de partager des données, des codes, et de participer à des compétitions de data-science).

Chacune des 9994 lignes du jeu de données concerne une vente réalisée. Les informations suivantes sont disponibles pour chaque vente :

Nom de variable Type Description
Row ID double identifiant numérique unique de la transaction (numéro de ligne)
Order ID' character identifiant unique de la transaction
Order Date datetime date de la commande
Ship Date datetime date de l’envoi de la commande
Ship Mode character type d’envoi de la commande (First Class, Same Day, Second Class, et Standard Class)
Customer ID character Identifiant de l’acheteur
Customer Name character Nom de l’acheteur
Segment character Segment de vente (Consumer, Corporate, Home Office)
Country character Pays de résidence du client (United States)
City character Ville de résidence du client
State character État de résidence du client
Postal Code character Code postal de résidence du client
Region character Région de résidence du client (Central, East, South, West)
Product ID character Identifiant du produit
Category character Catégorie du produit (Furniture, Office Supplies, Technology)
Sub-Category character Sous-catégorie du produit
Product Name character Nom du produit
Sales double Prix total de la vente (prix unitaire multiplié par les quantités, avec remise éventuelle)
Quantity double Quantité vendue
Discount double Taux de réduction (entre 0 et 0.8)
Profit double Profit réalisé

Comme lors de la première séance, vous allez devoir utiliser des fonctions du package {tidyverse} pour manipuler les données, et du package {readxl} pour importer les données dans R. Il faut donc charger ces deux packages.

  1. Chargez les packages {tidyverse} et {readxl}.
  2. Importez les données dans R et conservez-les dans un objet que vous appellerez ventes. Pour rappel, le fichier de données se nomme US Superstore data.xls et est contenu dans le dossier donnees.

La colonne Sales du tableau de données ventes indique le prix de la transaction. La valeur \(x\) correspond au calcul suivant :

\[x = \text{prix unitaire} \times \text{quantité} \times (1-\text{taux de réduction}).\]

Vous allez vous intéresser au chiffre d’affaires dans l’ensemble des exercices de cette séance.

2 Résumés statistiques

Des statistiques descriptives sur la colonne des ventes peuvent facilement être obtenues à l’aide des fonctions suivantes :

Le prix de la transaction moyenne s’établit à :

mean(ventes$Sales)
## [1] 229.858

avec un écart-type de :

sd(ventes$Sales)
## [1] 623.2451

Regardons l’étendue :

min(ventes$Sales)
## [1] 0.444
max(ventes$Sales)
## [1] 22638.48

La médiane :

median(ventes$Sales)
## [1] 54.49

Les premier et troisièmes quartiles :

# Premier quartile
quantile(ventes$Sales, probs = 0.25)
##   25% 
## 17.28
# Troisième quartile
quantile(ventes$Sales, probs = 0.75)
##    75% 
## 209.94

L’ensemble de ces informations peuvent s’obtenir d’un coup d’œil (sauf l’écart-type), à l’aide de la fonction summary() :

summary(ventes$Sales)
##      Min.   1st Qu.    Median      Mean   3rd Qu.      Max. 
##     0.444    17.280    54.490   229.858   209.940 22638.480

En cas de présence de valeurs manquantes (NA), les fonctions mean(), sd(), min, etc. retournent la valeur NA :

# Sans valeur NA, la moyenne du vecteur (1,2,3) est :
mean( c(1,2,3) )
## [1] 2
# Avec la présence d'au moins une valeur NA :
mean( c(1, NA,2,3) )
## [1] NA

Pour que les valeurs NA soient ignorées lors du calcul de ces fonctions de résumés statistiques, il suffit d’ajouter l’argument na.rm = TRUE à la fonction qui est appelée :

mean( c(1, NA,2,3), na.rm = TRUE )
## [1] 2

Pour obtenir le chiffre d’affaire totales sur la période couverte par les données, on peut calculer la somme de toutes les valeurs contenues dans la colonne Sales:

sum(ventes$Sales)
## [1] 2297201

À votre tour.

La colonne Quantity du tableau de données ventes fournit les quantités vendues pour chaque transaction effectuée.

  1. Calculez le nombre d’articles moyens par transaction, sur l’ensemble de la période.
  2. Calculez également son écart-type, son étendue, et les 3 quartiles.

3 Sélection d’une ou plusieurs colonnes

La fonction select() du package {tidyverse} permet de sélectionner une ou plusieurs colonnes. On donne un tableau de données comme premier argument à cette fonction. On indique ensuite la ou les noms des colonnes à conserver, en les séparant par une virgule. Admettons par exemple que l’on souhaite conserver uniquement les colonnes Customer ID, Sales, Quantity et Discount :

ventes_2 <- select(ventes, `Customer ID`, Sales, Quantity, Discount)
ventes_2
## # A tibble: 9,994 × 4
##    `Customer ID`  Sales Quantity Discount
##    <chr>          <dbl>    <dbl>    <dbl>
##  1 CG-12520      262.          2     0   
##  2 CG-12520      732.          3     0   
##  3 DV-13045       14.6         2     0   
##  4 SO-20335      958.          5     0.45
##  5 SO-20335       22.4         2     0.2 
##  6 BH-11710       48.9         7     0   
##  7 BH-11710        7.28        4     0   
##  8 BH-11710      907.          6     0.2 
##  9 BH-11710       18.5         3     0.2 
## 10 BH-11710      115.          5     0   
## # … with 9,984 more rows

Pour conserver l’ensemble des colonnes excepté certaines, il faut faire précéder le nom de ces colonnes que l’on souhaite ne pas conserver par le signe moins (-) dans la fonction select

select(ventes_2, -Quantity)
## # A tibble: 9,994 × 3
##    `Customer ID`  Sales Discount
##    <chr>          <dbl>    <dbl>
##  1 CG-12520      262.       0   
##  2 CG-12520      732.       0   
##  3 DV-13045       14.6      0   
##  4 SO-20335      958.       0.45
##  5 SO-20335       22.4      0.2 
##  6 BH-11710       48.9      0   
##  7 BH-11710        7.28     0   
##  8 BH-11710      907.       0.2 
##  9 BH-11710       18.5      0.2 
## 10 BH-11710      115.       0   
## # … with 9,984 more rows

À partir du tableau ventes, créez le tableau villes qui contiendra uniquement les colonnes City et State.

4 Création d’une nouvelle colonne

Le package {tidyverse} offre une fonction permettant de créer ou de modifier une colonne d’un tableau de données : mutate(). Son premier argument est le tableau de données, le ou les arguments suivants correspondent aux colonnes à créer ou modifier.

Pour illustrer le fonctionnement de cette méthode, regardons un premier exemple très simple : exprimons les prix de vente en milliers de dollars. La colonne Sales indique les prix en dollars. Créons la colonne sales_k qui exprime le prix total de la vente en milliers de dollars :

ventes <- mutate(ventes, sales_k = Sales / 1000)

Regardons les premières valeurs, à l’aide de la fonction select() :

select(ventes, Sales, sales_k)
## # A tibble: 9,994 × 2
##     Sales sales_k
##     <dbl>   <dbl>
##  1 262.   0.262  
##  2 732.   0.732  
##  3  14.6  0.0146 
##  4 958.   0.958  
##  5  22.4  0.0224 
##  6  48.9  0.0489 
##  7   7.28 0.00728
##  8 907.   0.907  
##  9  18.5  0.0185 
## 10 115.   0.115  
## # … with 9,984 more rows

Admettons à présent que l’on souhaite convertir ce montant en milliers d’euros. Utilisons, par simplicité, un taux de change tel qu’1 Dollar US équivaut à 0,89 Euro.

ventes <- mutate(ventes, sales_k_euros = sales_k * 0.89)

Regardons les valeurs :

select(ventes, Sales, sales_k, sales_k_euros)
## # A tibble: 9,994 × 3
##     Sales sales_k sales_k_euros
##     <dbl>   <dbl>         <dbl>
##  1 262.   0.262         0.233  
##  2 732.   0.732         0.651  
##  3  14.6  0.0146        0.0130 
##  4 958.   0.958         0.852  
##  5  22.4  0.0224        0.0199 
##  6  48.9  0.0489        0.0435 
##  7   7.28 0.00728       0.00648
##  8 907.   0.907         0.807  
##  9  18.5  0.0185        0.0165 
## 10 115.   0.115         0.102  
## # … with 9,984 more rows

Ces opérations en plusieurs étapes peuvent se réaliser à l’aide d’une seule instruction :

ventes <- mutate(ventes,
                 ventes, sales_k = Sales / 1000,
                 sales_k_euros = sales_k * 0.89)
select(ventes, Sales, sales_k, sales_k_euros)
## # A tibble: 9,994 × 3
##     Sales sales_k sales_k_euros
##     <dbl>   <dbl>         <dbl>
##  1 262.   0.262         0.233  
##  2 732.   0.732         0.651  
##  3  14.6  0.0146        0.0130 
##  4 958.   0.958         0.852  
##  5  22.4  0.0224        0.0199 
##  6  48.9  0.0489        0.0435 
##  7   7.28 0.00728       0.00648
##  8 907.   0.907         0.807  
##  9  18.5  0.0185        0.0165 
## 10 115.   0.115         0.102  
## # … with 9,984 more rows

Dans le tableau ventes, créez la colonne prix_unitaire. Pour ce faire, il vous fait effectuer le calcul suivant :

\[\text{Prix Unitaire} = \frac{\text{Sales}}{\text{Quantity} \times (1-\text{Discount})}\]

Puis, affichez les colonnes Sales, Quantity, Discount et prix_unitaire du tableau.

5 Extraction d’éléments d’une date

La colonne Order Date du tableau de données ventes indique la date d’achat pour chaque transaction. Utilisons cette colonne pour extraire des informations. Cette colonne contient un vecteur de classe POSIXct (une date). Le package {lubridate} permet de gérer très facilement les dates en R, et d’en extraire les éléments (comme le numéro du jour, celui du mois, de l’année, le jour de la semaine, etc.). Chargeons le package {lubridate} :

library(lubridate)

En R, il existe trois classes de dates :

Le stockage d’une date en R correspond au nombre de jours depuis 1970-01-01 (en valeurs négatives pour les dates antérieures). Le format standard est : %Y-%m-%d ou %Y/%m/%d (%Y : année sur 4 chiffres, %m : mois sur deux chiffres, %d : jour sur deux chiffres).

Les codes des formats sont accessibles sur la page d’aide de la fonction strptime() (on y accède en évaluant dans la console ?strptime()). Le tableau ci-dessous répertorie les éléments les plus courants :

Code Description Exemple
%a Abréviation du jour de la semaine (dépend du lieu) Mer
%A Jour de la semaine complet (dépend du lieu) Mercredi
%b Abréviation du mois (dépend du lieu) oct
%B Nom du mois complet (dépend du lieu) octobre
%d Jour du mois (01–31) 21
%D Date au format %m/%d/%y 10/21/15
%H Heure (00–24) 00
%m Mois (01–12) 10
%M Minute (00-59) 00
%S Seconde (00-61) 00
%Y Année (en input, uniquement de 0 à 9999) 2015
%z offset en heures et minutes par rapport au temps UTC +0000
%Z Abréviation du fuseau horraire (en output seulement) UTC

Trois fonctions sont proposées dans le package {lubridate} pour les dates sans heures, à appliquer pour convertir une chaîne de caractères en date :

Les lettres font référence à l’année (yyear), le mois (mmonth) et le jour (dday). La position des lettres dans le nom de la fonction indique l’ordre des éléments de la date dans la chaîne de caractètres qui est fournie en argument de la fonction.

Regardons avec la date de la séance. Si la date est notée dans la chaîne suivante : "2022-01-22", l’année vient en premier, suivie du mois, puis du jour. On utilise alors la fonction ymd():

ymd("2022-01-22")
## [1] "2022-01-22"

Si la date est contenue dans une chaîne de caractères fournissant un ordre français : “22/01/2022”, le jour vient en premier, suivi du mois, puis de l’année. On utilise alors la fonction dmy() :

dmy("22/01/2022")
## [1] "2022-01-22"

Si des indications sur les heures, minutes et secondes sont présentes dans les dates, il suffit d’ajouter d’un suffixe à la fonction de date : h (heures), ou hm (heures et minutes) ou hms (heures, minutes et secondes). Le même principe que pour y, m et d s’applique pour les positions de h, m et s.

ymd_hms("2022-01-22 08:45:20")
## [1] "2022-01-22 08:45:20 UTC"

Les fonctions reportées dans le tableau ci-dessous permettent d’extraire des éléments d’une date :

Fonction Extraction
second() secondes (0–59)
minute() minutes (0–59)
hour() heures (0–23)
day(), mday() jour du mois (1–31)
wday() jour de la semaine (1–7), le dimanche étant le 1
yday() jour de l’année (1–366)
week() numéro de la semaine dans l’année. Les semaines sont définies comme les pé- riodes complètes de 7 jours s’étant déroulées depuis le premier janvier, plus 1
isoweek() Semaine de l’année (00-53). Si la semaine (qui commence un lundi) qui contient le 1er janvier a 4 jours ou plus dans la nouvelle année, alors elle est considérée comme la semaine 1. Sinon, elle est considérée comme la dernière de l’année précédente, et la suivante est considérée comme semaine 1
month() mois (1–12)
year() année, uniquement celles après l’an 1
tz() fuseau horraire

Regardons quelques exemples avec la date du jour :

une_date <- ymd("2022-01-22")

Pour extraire le numéro du jour :

day(une_date)
## [1] 22

Celui du mois :

month(une_date)
## [1] 1

L’année :

year(une_date)
## [1] 2022

À votre tour

Soit la chaîne de caractères suivante :

jour <- "2022-01-23"
  1. Transformez cette chaîne de caractères en date, avec une fonction appropriée de {tidyverse}
  2. Une fois la date créée, extrayez : son mois, puis son année.
ventes <- 
  mutate(ventes, mois = month(`Order Date`))

6 Agrégation par groupes

La colonne Order Date du tableau de données ventes indique la date d’achat pour chaque transaction. Comme chaque ligne du tableau de données ventes représente une transaction, pour obtenir le chiffre d’affaire quotidien, il faut aggréger les données par jour.

L’aggrégation de valeurs selon des sous groupes peut être effectuée en deux étapes, à l’aide de deux fonctions du package {dplyr} (chargé lorsque l’on charge {tidyverse}) :

  1. group_by() : dans un premier temps, les données du tableau sont regroupées selon les modalités d’une ou de plusieurs colonnes. Il s’agit de créer des sous-groupes dans le tableau de données
  2. summarise() : dans un deuxième temps, les observations des lignes sont agrégées, résumées, pour chaque sous groupe.

Ici, pour obtenir le chiffre d’affaires quotidien, il faut regrouper les observations par journée (donc selon les valeurs différentes qui se trouvent dans la colonne Order Date) :

group_by(ventes, `Order Date`)
## # A tibble: 9,994 × 24
## # Groups:   Order Date [1,237]
##    `Row ID` `Order ID`     `Order Date`        `Ship Date`         `Ship Mode`  
##       <dbl> <chr>          <dttm>              <dttm>              <chr>        
##  1        1 CA-2016-152156 2016-11-08 00:00:00 2016-11-11 00:00:00 Second Class 
##  2        2 CA-2016-152156 2016-11-08 00:00:00 2016-11-11 00:00:00 Second Class 
##  3        3 CA-2016-138688 2016-06-12 00:00:00 2016-06-16 00:00:00 Second Class 
##  4        4 US-2015-108966 2015-10-11 00:00:00 2015-10-18 00:00:00 Standard Cla…
##  5        5 US-2015-108966 2015-10-11 00:00:00 2015-10-18 00:00:00 Standard Cla…
##  6        6 CA-2014-115812 2014-06-09 00:00:00 2014-06-14 00:00:00 Standard Cla…
##  7        7 CA-2014-115812 2014-06-09 00:00:00 2014-06-14 00:00:00 Standard Cla…
##  8        8 CA-2014-115812 2014-06-09 00:00:00 2014-06-14 00:00:00 Standard Cla…
##  9        9 CA-2014-115812 2014-06-09 00:00:00 2014-06-14 00:00:00 Standard Cla…
## 10       10 CA-2014-115812 2014-06-09 00:00:00 2014-06-14 00:00:00 Standard Cla…
## # … with 9,984 more rows, and 19 more variables: `Customer ID` <chr>,
## #   `Customer Name` <chr>, Segment <chr>, Country <chr>, City <chr>,
## #   State <chr>, `Postal Code` <dbl>, Region <chr>, `Product ID` <chr>,
## #   Category <chr>, `Sub-Category` <chr>, `Product Name` <chr>, Sales <dbl>,
## #   Quantity <dbl>, Discount <dbl>, Profit <dbl>, sales_k <dbl>,
## #   sales_k_euros <dbl>, mois <dbl>

On note dans la sortie précédente que cela correspond à 1237 groupes (il y a donc 1237 jours différents dans le tableau de données).

Une fois les groupes désignés, il reste à effectuer le calcul de résumé (du chiffre d’affaires) sur chacun des groupes, à l’aide de la fonction summarise(). Le chiffre d’affaire correspond à la somme des ventes effectuées, il s’agit donc d’effectuer une somme des valeurs de la colonne Order Date pour chaque groupe. Le résultat du calcul sera donné dans une colonne que l’on pourra nommer, par exemple, chiffre_affaire.

ca_quotidien <- 
  summarise(group_by(ventes, `Order Date`), chiffre_affaire = sum(Sales))

Pour éviter d’écrire les compositions de fonctions de manière condensée comme dans l’exemple précédent, le package {magrittr} propose un opérateur nommé “pipe”, dont la syntaxe est la suivante %>%.

Cet opérateur fournit le résultat de l’évaluation de ce qui se trouve avant lui en premier argument de la fonction qui se situe immédiatement après.

ca_quotidien <- 
  ventes %>% 
  group_by(`Order Date`) %>% 
  summarise(chiffre_affaire = sum(Sales))

Le code devient plus facile à lire :

  • on part du tableau de données ventes ;
  • ce tableau est donné en premier argument de la fonction group_by() ;
  • le regroupement est fait selon la colonne Order Date ;
  • une fois le regroupement effectué, le résultat est donné comme premier argument de la fonction summarise() ;
  • le calcul de la somme des valeurs de la colonne Sales est effectué pour chaque groupe du tableau de données, et le résultat est indiqué dans une colonne nommée chiffre_affaire.

Visualisons les valeurs du chiffre d’affaire quotidien. Vous apprendrez à faire des graphiques lors d’autres séances. Pour l’heure, regardons simplement le résultat.

ggplot(data = ca_quotidien, 
       mapping = aes(x = `Order Date`, y = chiffre_affaire)) +
  geom_line() +
  labs(x = "Date d'achat", y = "Chiffre d'affaire",
       title = "Chiffre d'affaire quotidien")

On peut noter qu’il y a de fortes variations.

7 Filtrage

Pour conserver uniquement les lignes d’un tableau qui remplissent les conditions d’un filtre, la fonction filter() du package {dplyr} s’avère être très pratique. Cette fonction fait partie de l’environnement {tidyverse}, s’applique directement à un tableau de données, et retourne un tableau de données comprenant les lignes pour lesquels le filtre retourne une valeur logique TRUE.

Le premier argument de la fonction filter() est le tableau de données. Les arguments suivants correspondent au(x) filtre(s) à appliquer. Par exemple, pour conserver uniquement les lignes du tableau ventes pour lesquelles le montant de la transaction dépasse 6000 dollars, on écrira :

filter(ventes, Sales > 6000)
## # A tibble: 15 × 24
##    `Row ID` `Order ID`     `Order Date`        `Ship Date`         `Ship Mode`  
##       <dbl> <chr>          <dttm>              <dttm>              <chr>        
##  1      166 CA-2014-139892 2014-09-08 00:00:00 2014-09-12 00:00:00 Standard Cla…
##  2      510 CA-2015-145352 2015-03-16 00:00:00 2015-03-22 00:00:00 Standard Cla…
##  3      684 US-2017-168116 2017-11-04 00:00:00 2017-11-04 00:00:00 Same Day     
##  4     2506 CA-2014-143917 2014-07-25 00:00:00 2014-07-27 00:00:00 Second Class 
##  5     2624 CA-2017-127180 2017-10-22 00:00:00 2017-10-24 00:00:00 First Class  
##  6     2698 CA-2014-145317 2014-03-18 00:00:00 2014-03-23 00:00:00 Standard Cla…
##  7     4099 CA-2014-116904 2014-09-23 00:00:00 2014-09-28 00:00:00 Standard Cla…
##  8     4191 CA-2017-166709 2017-11-17 00:00:00 2017-11-22 00:00:00 Standard Cla…
##  9     4278 US-2016-107440 2016-04-16 00:00:00 2016-04-20 00:00:00 Standard Cla…
## 10     6426 CA-2016-143714 2016-05-23 00:00:00 2016-05-27 00:00:00 Standard Cla…
## 11     6627 CA-2014-145541 2014-12-14 00:00:00 2014-12-21 00:00:00 Standard Cla…
## 12     6827 CA-2016-118689 2016-10-02 00:00:00 2016-10-09 00:00:00 Standard Cla…
## 13     8154 CA-2017-140151 2017-03-23 00:00:00 2017-03-25 00:00:00 First Class  
## 14     8489 CA-2016-158841 2016-02-02 00:00:00 2016-02-04 00:00:00 Second Class 
## 15     9040 CA-2016-117121 2016-12-17 00:00:00 2016-12-21 00:00:00 Standard Cla…
## # … with 19 more variables: `Customer ID` <chr>, `Customer Name` <chr>,
## #   Segment <chr>, Country <chr>, City <chr>, State <chr>, `Postal Code` <dbl>,
## #   Region <chr>, `Product ID` <chr>, Category <chr>, `Sub-Category` <chr>,
## #   `Product Name` <chr>, Sales <dbl>, Quantity <dbl>, Discount <dbl>,
## #   Profit <dbl>, sales_k <dbl>, sales_k_euros <dbl>, mois <dbl>

Pour chaque ligne, le test logique consistant à regarder si la valeur de la colonne Sales est strictement supérieure à 6000 est réalisé. Si la valeur retournée est TRUE, la ligne est retournée. Dans tous les autres cas, la ligne est retirée du résultat.

Des filtres plus complexes peuvent être réalisés, à l’aide des opérateurs logiques suivants :

Par exemple, pour obtenir les lignes dont la valeur de la colonne Sales est comprise dans l’intervalle \([6000;8000Ø\), on écrira :

filter(ventes, Sales >= 6000 & Sales <= 8000)
## # A tibble: 3 × 24
##   `Row ID` `Order ID`     `Order Date`        `Ship Date`         `Ship Mode`   
##      <dbl> <chr>          <dttm>              <dttm>              <chr>         
## 1      510 CA-2015-145352 2015-03-16 00:00:00 2015-03-22 00:00:00 Standard Class
## 2      684 US-2017-168116 2017-11-04 00:00:00 2017-11-04 00:00:00 Same Day      
## 3     6627 CA-2014-145541 2014-12-14 00:00:00 2014-12-21 00:00:00 Standard Class
## # … with 19 more variables: `Customer ID` <chr>, `Customer Name` <chr>,
## #   Segment <chr>, Country <chr>, City <chr>, State <chr>, `Postal Code` <dbl>,
## #   Region <chr>, `Product ID` <chr>, Category <chr>, `Sub-Category` <chr>,
## #   `Product Name` <chr>, Sales <dbl>, Quantity <dbl>, Discount <dbl>,
## #   Profit <dbl>, sales_k <dbl>, sales_k_euros <dbl>, mois <dbl>

Pour conserver les lignes pour lesquelles la valeur d’une colonne fait partie d’un ensemble de valeurs, on utilise l’opérateur %in%. Par exemple, pour conserver les observations du tableau ventes pour lesquelles la commande est passée par un•e client•e venant soit de la Californie, soit de la Floride, on écrira :

filter(ventes, State %in% c("California", "Florida"))
## # A tibble: 2,384 × 24
##    `Row ID` `Order ID`     `Order Date`        `Ship Date`         `Ship Mode`  
##       <dbl> <chr>          <dttm>              <dttm>              <chr>        
##  1        3 CA-2016-138688 2016-06-12 00:00:00 2016-06-16 00:00:00 Second Class 
##  2        4 US-2015-108966 2015-10-11 00:00:00 2015-10-18 00:00:00 Standard Cla…
##  3        5 US-2015-108966 2015-10-11 00:00:00 2015-10-18 00:00:00 Standard Cla…
##  4        6 CA-2014-115812 2014-06-09 00:00:00 2014-06-14 00:00:00 Standard Cla…
##  5        7 CA-2014-115812 2014-06-09 00:00:00 2014-06-14 00:00:00 Standard Cla…
##  6        8 CA-2014-115812 2014-06-09 00:00:00 2014-06-14 00:00:00 Standard Cla…
##  7        9 CA-2014-115812 2014-06-09 00:00:00 2014-06-14 00:00:00 Standard Cla…
##  8       10 CA-2014-115812 2014-06-09 00:00:00 2014-06-14 00:00:00 Standard Cla…
##  9       11 CA-2014-115812 2014-06-09 00:00:00 2014-06-14 00:00:00 Standard Cla…
## 10       12 CA-2014-115812 2014-06-09 00:00:00 2014-06-14 00:00:00 Standard Cla…
## # … with 2,374 more rows, and 19 more variables: `Customer ID` <chr>,
## #   `Customer Name` <chr>, Segment <chr>, Country <chr>, City <chr>,
## #   State <chr>, `Postal Code` <dbl>, Region <chr>, `Product ID` <chr>,
## #   Category <chr>, `Sub-Category` <chr>, `Product Name` <chr>, Sales <dbl>,
## #   Quantity <dbl>, Discount <dbl>, Profit <dbl>, sales_k <dbl>,
## #   sales_k_euros <dbl>, mois <dbl>

À votre tour.

  1. Filtrez le tableau ventes pour ne conserver que les lignes pour lesquelles la valeur de la colonne Quantity est supérieure à 5.
  2. Filtrez le tableau ventes pour ne conserver que les lignes correspondant à des commandes passées au mois de janvier ou au mois de février.
  3. Filtrez le tableau ventes pour ne conserver que les lignes pour lesquelles la valeur de la colonne Category est soit Furniture, soit Office Supplies. Stockez le résultat dans un objet que vous appellerez categories.
  4. À partir du tableau categories, utilisez la fonction count() du package {dplyr} pour compter le nombre d’observations pour lesquelles la valeur dans la colonne Category est Furniture et pour lesquelles la valeur est Office Supplies (Indice : pensez à utiliser la fonction group_by() de {dplyr} avant d’utiliser la fonction count())

8 Tri

La fonction arrange() du package {dplyr} permet d’ordonner les observations par valeurs croissantes ou décroissantes d’une ou de plusieurs colonnes. À nouveau, le premier argument attendu est un tableau de données, et le résultat est un tableau de données. Les arguments suivants sont les noms des colonnes sur lesquels effectuer le tri. Par défaut, le tri se fait par valeurs croissantes.

Par exemple, pour trier les valeurs par valeurs croissantes de la colonne Sales, on écrit simplement :

arrange(ventes, Sales)
## # A tibble: 9,994 × 24
##    `Row ID` `Order ID`     `Order Date`        `Ship Date`         `Ship Mode`  
##       <dbl> <chr>          <dttm>              <dttm>              <chr>        
##  1     4102 US-2017-102288 2017-06-19 00:00:00 2017-06-23 00:00:00 Standard Cla…
##  2     9293 CA-2017-124114 2017-03-02 00:00:00 2017-03-02 00:00:00 Same Day     
##  3     8659 CA-2016-168361 2016-06-21 00:00:00 2016-06-25 00:00:00 Standard Cla…
##  4     4712 CA-2014-112403 2014-03-31 00:00:00 2014-03-31 00:00:00 Same Day     
##  5     2107 US-2014-152723 2014-09-26 00:00:00 2014-09-26 00:00:00 Same Day     
##  6     7549 CA-2014-103492 2014-10-10 00:00:00 2014-10-15 00:00:00 Standard Cla…
##  7     8034 CA-2015-119690 2015-06-25 00:00:00 2015-06-28 00:00:00 First Class  
##  8     2762 CA-2017-126536 2017-10-12 00:00:00 2017-10-14 00:00:00 First Class  
##  9     8025 CA-2014-129189 2014-07-21 00:00:00 2014-07-25 00:00:00 Standard Cla…
## 10     1333 CA-2014-122567 2014-02-16 00:00:00 2014-02-21 00:00:00 Standard Cla…
## # … with 9,984 more rows, and 19 more variables: `Customer ID` <chr>,
## #   `Customer Name` <chr>, Segment <chr>, Country <chr>, City <chr>,
## #   State <chr>, `Postal Code` <dbl>, Region <chr>, `Product ID` <chr>,
## #   Category <chr>, `Sub-Category` <chr>, `Product Name` <chr>, Sales <dbl>,
## #   Quantity <dbl>, Discount <dbl>, Profit <dbl>, sales_k <dbl>,
## #   sales_k_euros <dbl>, mois <dbl>

Pour mieux visualiser le résultat, sélectionnons a priori seulement les colonnes Row ID, Customer ID, et Sales:

ventes %>% 
  select(`Row ID`, `Customer ID`, Sales) %>% 
  arrange(Sales)
## # A tibble: 9,994 × 3
##    `Row ID` `Customer ID` Sales
##       <dbl> <chr>         <dbl>
##  1     4102 ZC-21910      0.444
##  2     9293 RS-19765      0.556
##  3     8659 KB-16600      0.836
##  4     4712 JO-15280      0.852
##  5     2107 HG-14965      0.876
##  6     7549 CM-12715      0.898
##  7     8034 MV-17485      0.984
##  8     2762 NK-18490      0.99 
##  9     8025 HM-14860      1.04 
## 10     1333 MN-17935      1.08 
## # … with 9,984 more rows

Pour trier par valeurs décroissantes, on applique la fonction desc() sur le nom de la colonne, à l’intérieur de la fonction arrange :

ventes %>% 
  select(`Row ID`, `Customer ID`, Sales) %>% 
  arrange(desc(Sales))
## # A tibble: 9,994 × 3
##    `Row ID` `Customer ID`  Sales
##       <dbl> <chr>          <dbl>
##  1     2698 SM-20320      22638.
##  2     6827 TC-20980      17500.
##  3     8154 RB-19360      14000.
##  4     2624 TA-21385      11200.
##  5     4191 HL-15040      10500.
##  6     9040 AB-10105       9893.
##  7     4099 SC-20095       9450.
##  8     4278 BS-11365       9100.
##  9     8489 SE-20110       8750.
## 10     6426 CC-12370       8400.
## # … with 9,984 more rows

Lorsque une colonne utilisée pour faire un tri est une chaîne de caractères, l’ordre alphanumérique est utilisé :

tibble(colonne_a_trier = c("12", "23", "bonjour", " 
                           ", "bonjour 12", "\t", "\\",
                           "bonjour12",
                           "12 bonjour", "\n")) %>% 
  arrange(colonne_a_trier)
## # A tibble: 10 × 1
##    colonne_a_trier                 
##    <chr>                           
##  1 "\t"                            
##  2 "\n"                            
##  3 " \n                           "
##  4 "\\"                            
##  5 "12"                            
##  6 "12 bonjour"                    
##  7 "23"                            
##  8 "bonjour"                       
##  9 "bonjour 12"                    
## 10 "bonjour12"

Dans l’exemple précédent, les caractères spéciaux apparaissent en premier, suivis des valeurs numériques, puis par les lettres.

Pour trier par une colonne, puis par une autre, il suffit d’ajouter les noms des colonnes en arguments. L’ordre d’énumération définit l’ordre du tri. Par exemple, pour trier par valeurs croissantes des états (colonne State), puis, pour chaque état, par valeurs décroissantes des montants de vente (colonne Sales) :

ventes %>% 
  select(`Row ID`, `Customer ID`, State, Sales) %>% 
  arrange(State, desc(Sales))
## # A tibble: 9,994 × 4
##    `Row ID` `Customer ID` State   Sales
##       <dbl> <chr>         <chr>   <dbl>
##  1     1455 MC-17425      Alabama 3040 
##  2     1434 IM-15070      Alabama 1820.
##  3     1977 AS-10225      Alabama 1395.
##  4     5517 KC-16255      Alabama 1320.
##  5     5927 RA-19885      Alabama 1216.
##  6     3819 NW-18400      Alabama 1057.
##  7      534 RL-19615      Alabama  980.
##  8     2016 AM-10705      Alabama  900.
##  9     3705 DH-13075      Alabama  900.
## 10     3817 NW-18400      Alabama  802.
## # … with 9,984 more rows

Pour avoir une meilleure idée de ce qu’il se passe, regardons avec un plus petit tableau. Considérons le tableau suivant :

tableau <- 
  tibble(
    numero_ligne_initial = c(1,2,3,4),
    State = c("Florida", "California", "California", "Florida"),
    Sales = c(40,20,30,10))
tableau
## # A tibble: 4 × 3
##   numero_ligne_initial State      Sales
##                  <dbl> <chr>      <dbl>
## 1                    1 Florida       40
## 2                    2 California    20
## 3                    3 California    30
## 4                    4 Florida       10

Si on ordonne uniquement par la colonne State, par valeurs croissantes :

arrange(tableau, State)
## # A tibble: 4 × 3
##   numero_ligne_initial State      Sales
##                  <dbl> <chr>      <dbl>
## 1                    2 California    20
## 2                    3 California    30
## 3                    1 Florida       40
## 4                    4 Florida       10

Les lignes où State vaut "California" sont remontées avant celles où State vaut "Florida".

Si on veut, une fois ce tri effectué, trier par valeurs décroissantes de Sales, en conservant les observations pour la Californie avant celles de la Floride :

arrange(tableau, State, desc(Sales))
## # A tibble: 4 × 3
##   numero_ligne_initial State      Sales
##                  <dbl> <chr>      <dbl>
## 1                    3 California    30
## 2                    2 California    20
## 3                    1 Florida       40
## 4                    4 Florida       10

À votre tour.

  1. Trier le tableau ventes par valeurs décroissante des dates d’achat (colonne Order Date) .
  2. Trier le tableau ventes par valeurs décroissante des dates d’achat (colonne Order Date) et valeurs décroissantes des montants (colonne Sales).
  3. Affichez le top 3 des commandes par région. Pour ce faire :
  • regroupez les les observations par état (colonne State),
  • triez les observations par valeurs décroissantes des montants (colonne Sales),
  • utilisez la fonction slice() sur le tableau trié (et groupé) pour extraire uniquement les 3 premières observations de chaque groupe.

9 Jointures

Il n’est pas rare d’avoir deux tableaux de données qui disposent d’une ou de plusieurs colonnes communes, et qui peuvent être joints. Par exemple, un premier tableau peut nous donner l’ensemble des ventes réalisées par une entreprise (comme le tableau ventes) et un second tableau peut contenir les informations personnelles des client•es. Ces deux tableaux peuvent être mis en commun, à l’aide d’une jointure, pour calculer des statistiques sur le premier tableau, relativement à une information contenue dans le deuxième tableau.

Considérons un cas simplifié ici. Admettons que l’on dispose de deux deux tableaux :

ventes_2 <-
  tibble(
    montant = c(10, 12, 9, 15, 4, 24, 11, 8),
    id_client = c(1,2,1,3,2,3,2,5),
    date_commande = ymd("2022-02-23", "2022-02-23", "2022-02-24",
                        "2022-02-25", "2022-02-25", "2022-02-26",
                        "2022-02-26", "2022-02-26"))
ventes_2
## # A tibble: 8 × 3
##   montant id_client date_commande
##     <dbl>     <dbl> <date>       
## 1      10         1 2022-02-23   
## 2      12         2 2022-02-23   
## 3       9         1 2022-02-24   
## 4      15         3 2022-02-25   
## 5       4         2 2022-02-25   
## 6      24         3 2022-02-26   
## 7      11         2 2022-02-26   
## 8       8         5 2022-02-26
clients <- 
  tibble(
    id_client = c(1,2,3,4),
    nom = c("Sorel", "Auberjonois", "Hajjar", "Rouze") ,
    prenom = c("Albertine", "Viollette", "Adnan", "Arnaud"),
    ville = c("Fougères", "Saint-Malo", "Allauch", "Marseille"),
    departement = c("Ille-et-Vilaine", "Ille-et-Vilaine", "Bouches du Rhône", "Bouches du Rhône")
  )
clients
## # A tibble: 4 × 5
##   id_client nom         prenom    ville      departement     
##       <dbl> <chr>       <chr>     <chr>      <chr>           
## 1         1 Sorel       Albertine Fougères   Ille-et-Vilaine 
## 2         2 Auberjonois Viollette Saint-Malo Ille-et-Vilaine 
## 3         3 Hajjar      Adnan     Allauch    Bouches du Rhône
## 4         4 Rouze       Arnaud    Marseille  Bouches du Rhône

Une multitude de fonctions de jointure sont disponibles. Elles partagent une syntaxe commune :

xx_join(x, y, by = NULL, copy = FALSE, ...),

x et y sont les tableaux à joindre, by est un vecteur de chaînes de caractères contenant les noms des variables permettant la jointure (si la valeur est NULL – par défaut – la jointure se fera à l’aide des variables portant le même nom dans les deux tables).

Les différentes fonctions de jointure sont les suivantes :

inner_join(ventes_2, clients, by = c("id_client" = "id_client"))
## # A tibble: 7 × 7
##   montant id_client date_commande nom         prenom    ville      departement  
##     <dbl>     <dbl> <date>        <chr>       <chr>     <chr>      <chr>        
## 1      10         1 2022-02-23    Sorel       Albertine Fougères   Ille-et-Vila…
## 2      12         2 2022-02-23    Auberjonois Viollette Saint-Malo Ille-et-Vila…
## 3       9         1 2022-02-24    Sorel       Albertine Fougères   Ille-et-Vila…
## 4      15         3 2022-02-25    Hajjar      Adnan     Allauch    Bouches du R…
## 5       4         2 2022-02-25    Auberjonois Viollette Saint-Malo Ille-et-Vila…
## 6      24         3 2022-02-26    Hajjar      Adnan     Allauch    Bouches du R…
## 7      11         2 2022-02-26    Auberjonois Viollette Saint-Malo Ille-et-Vila…
left_join(ventes_2, clients, by = c("id_client" = "id_client"))
## # A tibble: 8 × 7
##   montant id_client date_commande nom         prenom    ville      departement  
##     <dbl>     <dbl> <date>        <chr>       <chr>     <chr>      <chr>        
## 1      10         1 2022-02-23    Sorel       Albertine Fougères   Ille-et-Vila…
## 2      12         2 2022-02-23    Auberjonois Viollette Saint-Malo Ille-et-Vila…
## 3       9         1 2022-02-24    Sorel       Albertine Fougères   Ille-et-Vila…
## 4      15         3 2022-02-25    Hajjar      Adnan     Allauch    Bouches du R…
## 5       4         2 2022-02-25    Auberjonois Viollette Saint-Malo Ille-et-Vila…
## 6      24         3 2022-02-26    Hajjar      Adnan     Allauch    Bouches du R…
## 7      11         2 2022-02-26    Auberjonois Viollette Saint-Malo Ille-et-Vila…
## 8       8         5 2022-02-26    <NA>        <NA>      <NA>       <NA>
right_join(ventes_2, clients, by = c("id_client" = "id_client"))
## # A tibble: 8 × 7
##   montant id_client date_commande nom         prenom    ville      departement  
##     <dbl>     <dbl> <date>        <chr>       <chr>     <chr>      <chr>        
## 1      10         1 2022-02-23    Sorel       Albertine Fougères   Ille-et-Vila…
## 2      12         2 2022-02-23    Auberjonois Viollette Saint-Malo Ille-et-Vila…
## 3       9         1 2022-02-24    Sorel       Albertine Fougères   Ille-et-Vila…
## 4      15         3 2022-02-25    Hajjar      Adnan     Allauch    Bouches du R…
## 5       4         2 2022-02-25    Auberjonois Viollette Saint-Malo Ille-et-Vila…
## 6      24         3 2022-02-26    Hajjar      Adnan     Allauch    Bouches du R…
## 7      11         2 2022-02-26    Auberjonois Viollette Saint-Malo Ille-et-Vila…
## 8      NA         4 NA            Rouze       Arnaud    Marseille  Bouches du R…
semi_join(ventes_2, clients, by = c("id_client" = "id_client"))
## # A tibble: 7 × 3
##   montant id_client date_commande
##     <dbl>     <dbl> <date>       
## 1      10         1 2022-02-23   
## 2      12         2 2022-02-23   
## 3       9         1 2022-02-24   
## 4      15         3 2022-02-25   
## 5       4         2 2022-02-25   
## 6      24         3 2022-02-26   
## 7      11         2 2022-02-26
anti_join(ventes_2, clients, by = c("id_client" = "id_client"))
## # A tibble: 1 × 3
##   montant id_client date_commande
##     <dbl>     <dbl> <date>       
## 1       8         5 2022-02-26

Si la jointure s’effectue à l’aide de deux colonnes ou plus, on donner au paramètre by de la fonction de jointure un vecteur comportant plusieurs éléments, chaque élément indiquant la correspondance entre les noms de colonnes dans les deux tableaux.

La syntaxe est la suivante, si la colonne nom_colonne_1_x du tableau x correspond à la colonne nom_colonne_1_y du tableau y, et si la colonne nom_colonne_2_x du tableau x correspond à la colonne nom_colonne_2_y du tableau y.

xx_join(x, y, by = c("nom_colonne_1_x" = "nom_colonne_1_y",
                     "nom_colonne_2_x" = "nom_colonne_2_y"))

À votre tour.

Considérons que le montant de TVA à retourner au service des impôts est donné selon le barème suivant, spécifique à chaque état.

tva <- 
  tibble(
    state = c(
      "Alabama","Alaska","Arizona","Arkansas","California","Colorado",
      "Connecticut","Delaware","District of Columbia","Florida",
      "Georgia","Hawaii","Idaho","Illinois","Indiana","Iowa",
      "Kansas","Kentucky","Louisiana","Maine","Maryland","Massachusetts",
      "Michigan","Minnesota","Mississippi","Missouri","Montana","Nebraska",
      "Nevada","New Hampshire","New Jersey","New Mexico","New York","North Carolina",
      "North Dakota","Ohio","Oklahoma","Oregon","Pennsylvania","Puerto Rico",
      "Rhode Island","South Carolina","South Dakota","Tennessee","Texas","Utah",
      "Vermont","Virginia","Washington","West Virginia","Wisconsin","Wyoming"),
    tva = c(
      4.00,0.00,5.60,6.50,7.25,2.90,6.35,0.00,6.00,6.00,4.00,4.00,6.00,6.25,7.00,6.00,
      6.50,6.00,4.45,5.50,6.00,6.25,6.00,6.875,7.00,4.23,0.00,5.50,6.85,0.00,6.63,5.13,
      4.00,4.75,5.00,5.75,4.50,0.00,6.00,11.50,7.00,6.00,4.50,7.00,6.25,4.85,6.00,4.30,
      6.50,6.00,5.00,4.00
    )
  )
  1. Copiez/collez le code précédent pour créer le tableau tva contenant les taux de la taxe sur la valeur ajoutée, par état.

  2. Créez le tableau ventes_3 à partir du tableau ventes, contenant les colonnes suivantes :

    • Order ID, Order Date, State, Sales
  3. À l’aide d’une jointure, ajoutez le taux de TVA au tableau ventes_3, en effectuant la jointure par la colonne State.

  4. Calculez les montants de TVA pour chaque transaction, en créant une nouvelle colonne que vous appellerez montant_tva.