Manipuler, formater et visualiser les données en toute simplicité
Groupe BioStatInfo
Un sage a dit un jour …
“Happy families are all alike; every unhappy family is unhappy in its own way.” –– Leo Tolstoy
… et celui qui nous intéresse aujourd’hui a renchéri :
“Tidy datasets are all alike, but every messy dataset is messy in its own way.” –– Hadley Wickham.
Messy and unhappy
Le monde du désordre est vaste …
# A tibble: 6 × 4
country year type count
<chr> <dbl> <chr> <dbl>
1 Afghanistan 1999 cases 745
2 Afghanistan 1999 population 19987071
3 Afghanistan 2000 cases 2666
4 Afghanistan 2000 population 20595360
5 Brazil 1999 cases 37737
6 Brazil 1999 population 172006362
… et varié
# A tibble: 6 × 3
country year rate
<chr> <dbl> <chr>
1 Afghanistan 1999 745/19987071
2 Afghanistan 2000 2666/20595360
3 Brazil 1999 37737/172006362
4 Brazil 2000 80488/174504898
5 China 1999 212258/1272915272
6 China 2000 213766/1280428583
Messy and unhappy
Parfois même fragmenté et dispersé !
# A tibble: 3 × 3
country `1999` `2000`
<chr> <dbl> <dbl>
1 Afghanistan 745 2666
2 Brazil 37737 80488
3 China 212258 213766
# A tibble: 3 × 3
country `1999` `2000`
<chr> <dbl> <dbl>
1 Afghanistan 19987071 20595360
2 Brazil 172006362 174504898
3 China 1272915272 1280428583
Heureusement il existe …
Une galaxie d’outils
Et une philosophie
Les 3 commandements du tidyverse :
Each variable must have its own column.
Each observation must have its own row.
Each value must have its own cell.
# A tibble: 6 × 4
country year cases population
<chr> <dbl> <dbl> <dbl>
1 Afghanistan 1999 745 19987071
2 Afghanistan 2000 2666 20595360
3 Brazil 1999 37737 172006362
4 Brazil 2000 80488 174504898
5 China 1999 212258 1272915272
6 China 2000 213766 1280428583
Installation et chargement
#install.packages("tidyverse") library(tidyverse)
Tidyverse est un meta-package, qui charge un ensemble de packages très pratiques, qui forment en quelque sorte la base du langage R moderne, pour un bon usage, propre et reproductible.
Nous allons voir par la suite quelques cas d’usage récurrents autour d’un même dataset illustratif.
country year cases population
1 Afghanistan 1999 745 19987071
2 Afghanistan 2000 2666 20595360
3 Brazil 1999 37737 172006362
4 Brazil 2000 80488 174504898
5 China 1999 212258 1272915272
6 China 2000 213766 1280428583
as_tibble(data_df)
# A tibble: 6 × 4
country year cases population
<chr> <dbl> <dbl> <dbl>
1 Afghanistan 1999 745 19987071
2 Afghanistan 2000 2666 20595360
3 Brazil 1999 37737 172006362
4 Brazil 2000 80488 174504898
5 China 1999 212258 1272915272
6 China 2000 213766 1280428583
magrittr: ceci est un pipe %>%
Introduit l’opérateur pipe%>% (ctrl+maj+m) qui permet d’enchainer les séquences d’instructions.
data %>%filter(year ==1999) %>%pull(cases) %>%mean()
[1] 83580
Depuis, R version 4.1, un opérateur pipe natif |> est disponible et voué à remplacer %>% à terme.
Commençons simplement par un problème récurrent, les données manquantes.
data[5,3] =NAdata
# A tibble: 6 × 4
country year cases population
<chr> <dbl> <dbl> <dbl>
1 Afghanistan 1999 745 19987071
2 Afghanistan 2000 2666 20595360
3 Brazil 1999 37737 172006362
4 Brazil 2000 80488 174504898
5 China 1999 NA 1272915272
6 China 2000 213766 1280428583
Plusieurs manières de traiter cette question.
La suppression des lignes avec des NA.
data %>%drop_na()
# A tibble: 5 × 4
country year cases population
<chr> <dbl> <dbl> <dbl>
1 Afghanistan 1999 745 19987071
2 Afghanistan 2000 2666 20595360
3 Brazil 1999 37737 172006362
4 Brazil 2000 80488 174504898
5 China 2000 213766 1280428583
Le remplacement par une valeur donnée.
data %>%replace_na(list(cases =42))
# A tibble: 6 × 4
country year cases population
<chr> <dbl> <dbl> <dbl>
1 Afghanistan 1999 745 19987071
2 Afghanistan 2000 2666 20595360
3 Brazil 1999 37737 172006362
4 Brazil 2000 80488 174504898
5 China 1999 42 1272915272
6 China 2000 213766 1280428583
Remplacement par une valeur précédente
data %>%fill(cases)
# A tibble: 6 × 4
country year cases population
<chr> <dbl> <dbl> <dbl>
1 Afghanistan 1999 745 19987071
2 Afghanistan 2000 2666 20595360
3 Brazil 1999 37737 172006362
4 Brazil 2000 80488 174504898
5 China 1999 80488 1272915272
6 China 2000 213766 1280428583
Remplacement par une valeur suivante
data %>%fill(cases, .direction ="up")
# A tibble: 6 × 4
country year cases population
<chr> <dbl> <dbl> <dbl>
1 Afghanistan 1999 745 19987071
2 Afghanistan 2000 2666 20595360
3 Brazil 1999 37737 172006362
4 Brazil 2000 80488 174504898
5 China 1999 213766 1272915272
6 China 2000 213766 1280428583
data %>%pivot_wider(names_from = country, values_from = cases)
# A tibble: 6 × 5
year population Afghanistan Brazil China
<dbl> <dbl> <dbl> <dbl> <dbl>
1 1999 19987071 745 NA NA
2 2000 20595360 2666 NA NA
3 1999 172006362 NA 37737 NA
4 2000 174504898 NA 80488 NA
5 1999 1272915272 NA NA 212258
6 2000 1280428583 NA NA 213766
data %>%pivot_wider(names_from = country, values_from =c(cases, population))
data %>%pivot_longer(cols =c(cases, population), names_to ="type", values_to ="number")
# A tibble: 12 × 4
country year type number
<chr> <dbl> <chr> <dbl>
1 Afghanistan 1999 cases 745
2 Afghanistan 1999 population 19987071
3 Afghanistan 2000 cases 2666
4 Afghanistan 2000 population 20595360
5 Brazil 1999 cases 37737
6 Brazil 1999 population 172006362
7 Brazil 2000 cases 80488
8 Brazil 2000 population 174504898
9 China 1999 cases 212258
10 China 1999 population 1272915272
11 China 2000 cases 213766
12 China 2000 population 1280428583
cheatsheet
S’il ne devait en rester qu’un, ce serait lui.
data %>%filter(year ==1999)
# A tibble: 3 × 4
country year cases population
<chr> <dbl> <dbl> <dbl>
1 Afghanistan 1999 745 19987071
2 Brazil 1999 37737 172006362
3 China 1999 212258 1272915272
data %>%slice(2:4)
# A tibble: 3 × 4
country year cases population
<chr> <dbl> <dbl> <dbl>
1 Afghanistan 2000 2666 20595360
2 Brazil 1999 37737 172006362
3 Brazil 2000 80488 174504898
data %>%slice_sample(prop =0.5) ## random sample
# A tibble: 3 × 4
country year cases population
<chr> <dbl> <dbl> <dbl>
1 China 2000 213766 1280428583
2 Afghanistan 1999 745 19987071
3 Brazil 1999 37737 172006362
data %>%select(c(country, cases))
# A tibble: 6 × 2
country cases
<chr> <dbl>
1 Afghanistan 745
2 Afghanistan 2666
3 Brazil 37737
4 Brazil 80488
5 China 212258
6 China 213766
data %>%pull(year)
[1] 1999 2000 1999 2000 1999 2000
data %>%summarize(mean_cases =mean(cases))
# A tibble: 1 × 1
mean_cases
<dbl>
1 91277.
data %>%count(country)
# A tibble: 3 × 2
country n
<chr> <int>
1 Afghanistan 2
2 Brazil 2
3 China 2