Comment compléter les lignes manquantes d'un jeu de données et les rendre explicites ?

🪰 Récemment, je me suis retrouvée avec un jeu de données correspondant à des piégeages d’insectes où les observations sans insectes piégés n’ont pas été notées.

Ça arrive et c’est normal.

⚙️ Sauf que quand il s’agit de faire des graphiques, puis des modèles stats, selon la question, il est parfois nécessaire de prendre en compte ces zéros !

💡 Ici, j’explique comment utiliser la fonction complete() du package tidyr pour ajouter les lignes manquantes et les remplir avec des zéros (où ce que tu veux !).

📦 Je montre un cas particulier où la structure des variables est emboîtée, ce qui fait que l’utilisation de complete() n’est pas tout à fait triviale.

Chargement des packages

library(tibble) # création de tables
library(tidyr) # nettoyage de tables
library(ggplot2) # graphiques
library(dplyr) # manipulation de tables

Remarque : les packages du tidyverse les plus couramment utilisés dont ceux présents ci-dessus peuvent être chargé en une seule ligne de commande avec library(tidyverse).

Création d’un jeu de données exemple

captures <- tribble(
     ~Site,    ~Date, ~Piege, ~Nb_captures,
  "Site A", "Date 1",    "a",           3L,
  "Site A", "Date 1",    "b",           2L,
  "Site A", "Date 2",    "a",           8L,
  "Site A", "Date 2",    "b",           5L,
  "Site A", "Date 3",    "a",           1L,
  "Site A", "Date 4",    "a",           3L,
  "Site A", "Date 4",    "b",           6L,
  "Site B", "Date 5",    "c",           3L,
  "Site B", "Date 5",    "d",           3L,
  "Site B", "Date 5",    "e",           2L,
  "Site B", "Date 6",    "c",           2L,
  "Site B", "Date 6",    "e",           7L,
  "Site B", "Date 7",    "c",           5L,
  "Site B", "Date 7",    "d",           4L,
  "Site B", "Date 7",    "e",           1L
  )

Il s’agit de données totalement fictives concernant 2 Sites échantillonnés respectivement à 2 et 3 endroits (Piege). L’objectif est de compter des individus à intervalles de temps régulier aux différents points de capture.

Deux points à noter :

  • Les Dates d’observation n’ont pas été les mêmes pour chaque site.
  • Quand aucun individu n’a été observé, il n’y a pas de ligne dans le jeu de données (dans l’exemple, dans le site A, la date 3 pour le piège b n’est pas présente)

Une table de contingence (qui compte le nombre d’occurence d’une combinaison d’événements) permet de mettre ça en évidence :

ftable(Site + Piege ~ Date, data = captures)
##        Site  Site A         Site B        
##        Piege      a b c d e      a b c d e
## Date                                      
## Date 1            1 1 0 0 0      0 0 0 0 0
## Date 2            1 1 0 0 0      0 0 0 0 0
## Date 3            1 0 0 0 0      0 0 0 0 0
## Date 4            1 1 0 0 0      0 0 0 0 0
## Date 5            0 0 0 0 0      0 0 1 1 1
## Date 6            0 0 0 0 0      0 0 1 0 1
## Date 7            0 0 0 0 0      0 0 1 1 1

ou alors

ftable(Site ~ Piege, data = captures)
##       Site Site A Site B
## Piege                   
## a               4      0
## b               3      0
## c               0      3
## d               0      2
## e               0      3

Si on fait un graphique à ce stade, ça donne, par exemple :

ggplot(captures) +
  aes(x = Date, y = Nb_captures, colour = Piege, group = Piege) +
  geom_line() +
  geom_point() +
  facet_wrap(~ Site, scales = "free_x")

C’est subtil, mais regarde bien : les lignes b et d ne passent pas par toutes les dates !

Ajout des observations manquantes pour les rendre explicite

La fonction complete() du package tidyr permet d’écrire de nouvelles lignes dans le jeu de données de telle sorte à préciser qu’il y avait 0 captures dans le piège ces jour-là !

Sauf que comme les dates et les noms des pièges ne sont pas les mêmes dans les 2 sites, ce n’est pas si simple, il faut le préciser à R.

Si on ne précise pas, toutes les combinaisons de site, piège et date sont créées :

captures %>% 
  complete(Site, Piege, Date, fill = list(Nb_captures = 0)) # fill permet de préciser la valeur de remplacement pour chaque colonne d'intérêt
## # A tibble: 70 × 4
##    Site   Piege Date   Nb_captures
##    <chr>  <chr> <chr>        <int>
##  1 Site A a     Date 1           3
##  2 Site A a     Date 2           8
##  3 Site A a     Date 3           1
##  4 Site A a     Date 4           3
##  5 Site A a     Date 5           0
##  6 Site A a     Date 6           0
##  7 Site A a     Date 7           0
##  8 Site A b     Date 1           2
##  9 Site A b     Date 2           5
## 10 Site A b     Date 3           0
## # ℹ 60 more rows

Or, on s’attend à récupérer :

  • 4 dates \(\times\) 2 points de capture = 8 lignes pour le site A
  • 3 dates \(\times\) 3 points de capture = 9 lignes pour le site B

Il faut préciser que les variables Piege et Date sont emboîtées dans la variable Site :

captures_complet <- captures %>% 
  group_by(Site) %>% # un calcul par site
  complete(Date, Piege, fill = list(Nb_captures = 0)) %>% # toutes les combinaisons de date et piège par site
  ungroup() # pour dégrouper le jeu de données

captures_complet
## # A tibble: 17 × 4
##    Site   Date   Piege Nb_captures
##    <chr>  <chr>  <chr>       <int>
##  1 Site A Date 1 a               3
##  2 Site A Date 1 b               2
##  3 Site A Date 2 a               8
##  4 Site A Date 2 b               5
##  5 Site A Date 3 a               1
##  6 Site A Date 3 b               0
##  7 Site A Date 4 a               3
##  8 Site A Date 4 b               6
##  9 Site B Date 5 c               3
## 10 Site B Date 5 d               3
## 11 Site B Date 5 e               2
## 12 Site B Date 6 c               2
## 13 Site B Date 6 d               0
## 14 Site B Date 6 e               7
## 15 Site B Date 7 c               5
## 16 Site B Date 7 d               4
## 17 Site B Date 7 e               1

Hop, et voilà : on obtient bien 8 + 9 lignes, cette fois.

Un petit graphique pour la fin :

ggplot(captures_complet) +
  aes(x = Date, y = Nb_captures, colour = Piege, group = Piege) +
  geom_line() +
  geom_point() +
  facet_wrap(~ Site, scales = "free_x")

Anna Doizy
Anna Doizy
Chercheuse, consultante et formatrice freelance
Libre comme l’R

Méthodologie scientifique et analyses de données statistiques