# A tibble: 6 × 4
prenom age categorie heures_tv
<chr> <dbl> <chr> <dbl>
1 Alice 22 Étudiant 1
2 Bilal 45 Cadre 3
3 Chloé 31 Employé 2
4 David 19 Étudiant 4
5 Éva 58 Cadre 2
6 Farid 27 Ouvrier 5
Décrire des données
L3 économie-finance
Reprise de la séance 2
Sur papier, sans machine
Voici un petit tableau de six personnes :
Sur papier, dessinez le tableau obtenu par chacun de ces deux enchaînements. Pas de machine.
tab |>
filter(categorie != "Étudiant") |>
arrange(age) |>
select(prenom, categorie)
tab |>
mutate(heures_semaine = heures_tv * 7) |>
filter(heures_semaine > 14)10 minutes de dessin individuel, puis correction collective au tableau. Regardez si les étudiants confondent filter et select, ou oublient que mutate ajoute une colonne sans retirer les autres.
Correction
tab <- tibble(
prenom = c("Alice", "Bilal", "Chloé", "David", "Éva", "Farid"),
age = c(22, 45, 31, 19, 58, 27),
categorie = c("Étudiant", "Cadre", "Employé", "Étudiant", "Cadre", "Ouvrier"),
heures_tv = c(1, 3, 2, 4, 2, 5)
)
tab |>
filter(categorie != "Étudiant") |>
arrange(age) |>
select(prenom, categorie)# A tibble: 4 × 2
prenom categorie
<chr> <chr>
1 Farid Ouvrier
2 Chloé Employé
3 Bilal Cadre
4 Éva Cadre
tab |>
mutate(heures_semaine = heures_tv * 7) |>
filter(heures_semaine > 14)# A tibble: 3 × 5
prenom age categorie heures_tv heures_semaine
<chr> <dbl> <chr> <dbl> <dbl>
1 Bilal 45 Cadre 3 21
2 David 19 Étudiant 4 28
3 Farid 27 Ouvrier 5 35
mutate() ajoute une colonne au tableau complet ; le filter() qui suit porte sur ce tableau augmenté, pas sur le tableau d’origine.
Où nous en sommes
Rappel
Lors de la dernière séance, nous avons appris à découper un tableau : select, filter, arrange, mutate.
d |> # d le tableau hdv2003 utilisé la semaine dernière
filter(age < 25) |>
select(age, sexe, qualif)# A tibble: 169 × 3
age sexe qualif
<int> <fct> <fct>
1 23 Femme <NA>
2 20 Femme <NA>
3 20 Femme <NA>
4 20 Femme Ouvrier specialise
5 19 Femme <NA>
6 23 Femme <NA>
7 23 Femme Ouvrier specialise
8 23 Homme Employe
9 22 Femme Employe
10 23 Femme <NA>
# ℹ 159 more rows
Aujourd’hui
- Résumer une variable quantitative : moyenne, dispersion, quartiles
- Compter les modalités d’une variable qualitative
- Comparer des groupes
- Croiser deux variables
Et une mise en garde : les calculs qui donnent un résultat faux sans rien dire.
Variables quantitatives
De quoi parle-t-on
Une variable quantitative est numérique et peut prendre un grand nombre de valeurs : ici l’âge (age) ou le nombre d’heures de télévision (heures.tv).
d |> select(age, heures.tv, freres.soeurs)# A tibble: 2,000 × 3
age heures.tv freres.soeurs
<int> <dbl> <int>
1 28 0 8
2 23 1 2
3 59 0 2
4 34 2 1
5 71 3 0
6 35 2 5
7 60 2.9 1
8 47 1 5
9 20 2 4
10 28 2 2
# ℹ 1,990 more rows
Résumer : summarise()
summarise() calcule des indicateurs sur l’ensemble du tableau et renvoie un tableau d’une seule ligne.
d |> summarise(
moyenne = mean(age),
mediane = median(age),
minimum = min(age),
maximum = max(age)
)# A tibble: 1 × 4
moyenne mediane minimum maximum
<dbl> <dbl> <int> <int>
1 48.2 48 18 97
Indicateurs de dispersion
Les indicateurs de dispersion mesurent si les valeurs sont regroupées ou dispersées.
Le plus simple est l’étendue : l’écart entre la plus grande et la plus petite valeur. Les plus utilisés sont la variance (var) et l’écart-type (sd, pour standard deviation).
d |> summarise(
etendue = max(age) - min(age),
variance = var(age),
ecart_type = sd(age)
)# A tibble: 1 × 3
etendue variance ecart_type
<int> <dbl> <dbl>
1 79 287. 16.9
Quartiles
- le premier quartile est la valeur en dessous de laquelle se trouvent 25 % des observations ;
- le deuxième quartile est la médiane : 50 % en dessous, 50 % au dessus ;
- le troisième quartile laisse 75 % des observations en dessous.
d |> summarise(
q1 = quantile(age, 0.25),
q2 = quantile(age, 0.50),
q3 = quantile(age, 0.75)
)# A tibble: 1 × 3
q1 q2 q3
<dbl> <dbl> <dbl>
1 35 48 60
L’argument de quantile() est une proportion entre 0 et 1 : 0.5 donne la médiane, 0.1 le premier décile.
Un résumé rapide
Pour un aperçu immédiat, summary() donne l’essentiel en une commande :
summary(d$age) Min. 1st Qu. Median Mean 3rd Qu. Max.
18.00 35.00 48.00 48.16 60.00 97.00
summary() attend un vecteur, d’où le $. C’est pratique pour explorer, mais le résultat n’est pas un tableau : on ne peut pas l’enchaîner avec |>. Pour produire un résultat réutilisable, préférez summarise().
Valeurs manquantes
d |> summarise(moyenne = mean(heures.tv))# A tibble: 1 × 1
moyenne
<dbl>
1 NA
Le résultat est NA. La variable contient des valeurs manquantes, et la moyenne d’un ensemble contenant une valeur inconnue est inconnue.
Écarter les valeurs manquantes
Comme en séance 1, l’argument na.rm = TRUE demande d’ignorer ces valeurs :
d |> summarise(
moyenne = mean(heures.tv, na.rm = TRUE),
nombre_na = sum(is.na(heures.tv))
)# A tibble: 1 × 2
moyenne nombre_na
<dbl> <int>
1 2.25 5
is.na() renvoie TRUE pour chaque valeur manquante ; sum() les compte.
Les erreurs silencieuses
Le vrai danger
En séance 1, nous avons vu comment lire un message d’erreur. Ces erreurs-là sont les faciles : R refuse de continuer, vous savez qu’il y a un problème.
À partir d’aujourd’hui, vous allez produire des chiffres. Et un chiffre faux ressemble exactement à un chiffre juste.
Il n’y a pas de message d’erreur pour vous prévenir qu’une moyenne porte sur la mauvaise population.
Trois pièges
na.rm = TRUEchange la population. Vous ne calculez plus la moyenne des 2000 enquêtés, mais celle des répondants. Comptez toujours combien vous en écartez.L’oubli du
<-. Vous croyez avoir créé une variable, elle n’existe pas. Les calculs suivants portent sur l’ancien tableau.Les effectifs faibles. Une moyenne calculée sur six personnes n’est pas comparable à une moyenne calculée sur huit cents. Affichez toujours l’effectif à côté de l’indicateur.
La parade
- Prédisez avant de lancer. Écrivez en commentaire l’ordre de grandeur que vous attendez. Un résultat qui surprend est soit une découverte, soit une erreur – il faut trancher, pas passer à la suite.
- Affichez toujours l’effectif à côté de chaque indicateur.
- Recoupez. Un même chiffre obtenu de deux façons différentes est probablement juste.
Variables qualitatives
De quoi parle-t-on
Une variable qualitative ne prend qu’un nombre limité de valeurs, appelées modalités : le sexe (sexe), le niveau d’études (nivetud), la catégorie socio-professionnelle (qualif).
Une variable qualitative peut être numérique, et certaines variables se traitent au choix comme quantitatives ou qualitatives : c’est le cas du nombre de frères et sœurs.
Tri à plat : count()
Le tri à plat compte le nombre d’observations pour chaque modalité.
d |> count(sexe)# A tibble: 2 × 2
sexe n
<fct> <int>
1 Homme 899
2 Femme 1101
Trier les effectifs
d |> count(qualif, sort = TRUE)# A tibble: 8 × 2
qualif n
<fct> <int>
1 Employe 594
2 <NA> 347
3 Ouvrier qualifie 292
4 Cadre 260
5 Ouvrier specialise 203
6 Profession intermediaire 160
7 Technicien 86
8 Autre 58
count() affiche les valeurs manquantes comme une modalité à part entière.
Passer aux pourcentages
Les effectifs bruts se comparent mal. On les rapporte au total avec mutate() :
d |>
count(qualif) |>
mutate(pourcentage = round(100 * n / sum(n), 1))# A tibble: 8 × 3
qualif n pourcentage
<fct> <int> <dbl>
1 Ouvrier specialise 203 10.2
2 Ouvrier qualifie 292 14.6
3 Technicien 86 4.3
4 Profession intermediaire 160 8
5 Cadre 260 13
6 Employe 594 29.7
7 Autre 58 2.9
8 <NA> 347 17.4
Exercice 1
- Faites le tri à plat de la variable
relig. Quelle est la modalité la plus fréquente ? - Exprimez ce tri à plat en pourcentages.
- Quelle proportion des enquêtés pratique la pêche ou la chasse (
peche.chasse) ? - Combien de valeurs manquantes contient la variable
trav.satisf? Que représentent-elles, à votre avis ?
20 minutes. La question 4 est importante : les NA de trav.satisf correspondent aux personnes sans emploi. Une valeur manquante a souvent un sens.
Comparer des groupes
group_by()
group_by() découpe le tableau en groupes ; summarise() calcule alors un résultat par groupe.
d |>
group_by(sexe) |>
summarise(
effectif = n(),
age_moyen = mean(age),
tv_moyenne = mean(heures.tv, na.rm = TRUE)
)# A tibble: 2 × 4
sexe effectif age_moyen tv_moyenne
<fct> <int> <dbl> <dbl>
1 Homme 899 48.2 2.22
2 Femme 1101 48.2 2.27
n() donne l’effectif du groupe. Prenez l’habitude de toujours l’inclure.
Grouper sur plusieurs variables
d |>
group_by(sexe, sport) |>
summarise(
effectif = n(),
age_moyen = mean(age),
.groups = "drop"
)# A tibble: 4 × 4
sexe sport effectif age_moyen
<fct> <fct> <int> <dbl>
1 Homme Non 530 53.3
2 Homme Oui 369 40.7
3 Femme Non 747 51.5
4 Femme Oui 354 41.1
.groups = "drop" supprime le regroupement une fois le calcul fait. Sans cet argument, R affiche un avertissement et le tableau reste groupé, ce qu’il faut garder en tête pour les opérations suivantes.
L’outil central du cours
C’est la combinaison la plus utile de tout ce que nous verrons :
découper en groupes (
group_by), calculer un indicateur par groupe (summarise), trier le résultat (arrange).
d |>
group_by(qualif) |>
summarise(
effectif = n(),
tv_moyenne = mean(heures.tv, na.rm = TRUE)
) |>
arrange(desc(tv_moyenne))# A tibble: 8 × 3
qualif effectif tv_moyenne
<fct> <int> <dbl>
1 Ouvrier specialise 203 3.00
2 Ouvrier qualifie 292 2.47
3 Employe 594 2.42
4 Technicien 86 2.11
5 Profession intermediaire 160 2.03
6 <NA> 347 2.01
7 Autre 58 1.87
8 Cadre 260 1.60
Exercice 2
- L’âge moyen varie-t-il selon le niveau d’études (
nivetud) ? - Les personnes qui déclarent lire des bandes dessinées sont-elles plus jeunes que les autres ?
- Comparez le nombre moyen d’heures de télévision selon la catégorie socio-professionnelle. Y a-t-il des groupes trop petits pour que la comparaison soit sérieuse ?
Écrivez en commentaire, avant de lancer, ce que vous attendez comme résultat.
Croiser deux variables
L’analyse bivariée
Faire une analyse bivariée, c’est étudier la relation entre deux variables : sont-elles liées ? Les valeurs de l’une influencent-elles celles de l’autre ? Ou sont-elles indépendantes ?
Compter les combinaisons
Pour croiser deux variables qualitatives, on compte les effectifs de chaque combinaison :
d |> count(qualif, sexe)# A tibble: 16 × 3
qualif sexe n
<fct> <fct> <int>
1 Ouvrier specialise Homme 96
2 Ouvrier specialise Femme 107
3 Ouvrier qualifie Homme 229
4 Ouvrier qualifie Femme 63
5 Technicien Homme 66
6 Technicien Femme 20
7 Profession intermediaire Homme 88
8 Profession intermediaire Femme 72
9 Cadre Homme 145
10 Cadre Femme 115
11 Employe Homme 96
12 Employe Femme 498
13 Autre Homme 21
14 Autre Femme 37
15 <NA> Homme 158
16 <NA> Femme 189
Une présentation en tableau
Le résultat précédent est correct mais peu lisible. pivot_wider() le remet en forme de tableau à double entrée :
d |>
count(qualif, sexe) |>
pivot_wider(names_from = sexe, values_from = n)# A tibble: 8 × 3
qualif Homme Femme
<fct> <int> <int>
1 Ouvrier specialise 96 107
2 Ouvrier qualifie 229 63
3 Technicien 66 20
4 Profession intermediaire 88 72
5 Cadre 145 115
6 Employe 96 498
7 Autre 21 37
8 <NA> 158 189
Pourcentages en ligne
Les effectifs bruts ne se comparent pas, car les groupes n’ont pas la même taille. On calcule donc les pourcentages à l’intérieur de chaque ligne :
d |>
count(qualif, sexe) |>
group_by(qualif) |>
mutate(pourcentage = round(100 * n / sum(n), 1)) |>
ungroup() |>
select(-n) |>
pivot_wider(names_from = sexe, values_from = pourcentage)# A tibble: 8 × 3
qualif Homme Femme
<fct> <dbl> <dbl>
1 Ouvrier specialise 47.3 52.7
2 Ouvrier qualifie 78.4 21.6
3 Technicien 76.7 23.3
4 Profession intermediaire 55 45
5 Cadre 55.8 44.2
6 Employe 16.2 83.8
7 Autre 36.2 63.8
8 <NA> 45.5 54.5
Ligne ou colonne ?
Le choix change complètement la lecture :
- pourcentages ligne : parmi les cadres, quelle part de femmes ?
- pourcentages colonne : parmi les femmes, quelle part de cadres ?
Pour obtenir les pourcentages colonne, on groupe par sexe au lieu de qualif.
Ce sont deux questions différentes, et deux tableaux différents, calculés sur les mêmes effectifs. Sachez toujours dire lequel des deux vous êtes en train de lire – c’est là que se logent la plupart des interprétations fausses.
Deux variables quantitatives
Pour deux variables numériques, on mesure la relation par la corrélation :
d |> summarise(
correlation = cor(age, heures.tv, use = "complete.obs")
)# A tibble: 1 × 1
correlation
<dbl>
1 0.178
use = "complete.obs" écarte les observations dont l’une des deux valeurs manque.
Une corrélation mesure une association linéaire, pas une causalité. Et une corrélation proche de zéro n’exclut pas une relation d’une autre forme – nous le verrons graphiquement la séance prochaine.
À vous
Exercices swirl
library(swirl)
swirl()Faites les leçons Valeurs_manquantes et Decrire_les_donnees.
En option, pour pratiquer davantage : la leçon facultative Exercice_2 reprend le chargement et le résumé d’un tableau. Voir LECONS_OPTIONNELLES.md.
Exercice 3
Produisez un court script commenté qui répond à :
- Quel est l’âge moyen des enquêtés, par catégorie socio-professionnelle ?
- Le nombre d’heures de télévision varie-t-il selon le niveau d’études ?
- Les hommes et les femmes déclarent-ils pratiquer un sport dans les mêmes proportions ?
Pour chaque question : l’effectif de chaque groupe à côté de l’indicateur et une phrase de commentaire disant ce que vous lisez dans le résultat.
Séance prochaine : les mêmes questions, mais en graphiques. Vous verrez que certaines choses invisibles dans un tableau sautent aux yeux dans un nuage de points.