Décrire des données

L3 économie-finance

Auteur·rice
Affiliation

Elias Bouacida

Université Paris 8

Date de publication

9 septembre 2026

Reprise de la séance 2

Sur papier, sans machine

Voici un petit tableau de six personnes :

# 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

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
Important

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 
Note

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.

Important

Il n’y a pas de message d’erreur pour vous prévenir qu’une moyenne porte sur la mauvaise population.

Trois pièges

  1. na.rm = TRUE change la population. Vous ne calculez plus la moyenne des 2000 enquêtés, mais celle des répondants. Comptez toujours combien vous en écartez.

  2. L’oubli du <-. Vous croyez avoir créé une variable, elle n’existe pas. Les calculs suivants portent sur l’ancien tableau.

  3. 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
Astuce

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

  1. Faites le tri à plat de la variable relig. Quelle est la modalité la plus fréquente ?
  2. Exprimez ce tri à plat en pourcentages.
  3. Quelle proportion des enquêtés pratique la pêche ou la chasse (peche.chasse) ?
  4. 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
Note

.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

  1. L’âge moyen varie-t-il selon le niveau d’études (nivetud) ?
  2. Les personnes qui déclarent lire des bandes dessinées sont-elles plus jeunes que les autres ?
  3. 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 ?
Astuce

É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.

Important

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.

Avertissement

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.

Note

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 à :

  1. Quel est l’âge moyen des enquêtés, par catégorie socio-professionnelle ?
  2. Le nombre d’heures de télévision varie-t-il selon le niveau d’études ?
  3. Les hommes et les femmes déclarent-ils pratiquer un sport dans les mêmes proportions ?
Astuce

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.