library(tidyverse)
ventes <- read_csv("data/ventes.csv", show_col_types = FALSE) |>
filter(!is.na(region), !is.na(quantite))
demo <- read_csv("data/demographie.csv", show_col_types = FALSE) |>
filter(age >= 18, age <= 100, revenu_mensuel < 20000)7 Exploration et statistiques descriptives
7.1 Introduction
Les statistiques descriptives résument un jeu de données sans encore généraliser à une population plus large. Elles répondent à : combien ? quelle tendance ? quelle dispersion ? quelles associations apparentes ?
7.2 Objectifs pédagogiques
- Calculer effectifs, tendances centrales et dispersion
- Lire quantiles, distributions et tableaux croisés
- Comparer des groupes
- Calculer et interpréter une corrélation (sans causalité)
- Éviter les erreurs d’interprétation courantes
7.3 Prérequis
- Notions de moyenne vues en Chapter 4.
7.4 Analyse exploratoire (EDA)
L’EDA combine tableaux et graphiques pour comprendre la structure avant toute modélisation. Questions types : valeurs manquantes ? asymétrie ? groupes très différents ? relations linéaires ?
- Tendance centrale : moyenne, médiane, mode
- Dispersion : étendue, variance, écart-type, IQR
- Distribution : comment les valeurs se répartissent
- Corrélation : association linéaire entre deux variables quantitatives
7.5 Effectifs et fréquences
# Effectifs
table(ventes$region)#>
#> Est Nord Ouest Sud
#> 50 47 59 42
# Fréquences relatives
prop.table(table(ventes$region)) |> round(3)#>
#> Est Nord Ouest Sud
#> 0.253 0.237 0.298 0.212
ventes |> count(region, sort = TRUE) |>
mutate(freq = n / sum(n))#> # A tibble: 4 × 3
#> region n freq
#> <chr> <int> <dbl>
#> 1 Ouest 59 0.298
#> 2 Est 50 0.253
#> 3 Nord 47 0.237
#> 4 Sud 42 0.212
7.6 Moyenne, médiane et mode
x <- ventes$montant
mean(x)#> [1] 130.5734
median(x)#> [1] 105.875
# Mode (valeur la plus fréquente) — pour variable discrète / qualitative
mode_stat <- function(v) {
tb <- sort(table(v), decreasing = TRUE)
names(tb)[1]
}
mode_stat(ventes$produit)#> [1] "Marqueur"
Interprétation : si moyenne ≫ médiane, la distribution est souvent tirée vers la droite (quelques gros montants). La médiane est plus robuste aux extrêmes.
# Démonstration avec un extreme
y <- c(10, 12, 11, 13, 12, 200)
mean(y)#> [1] 43
median(y)#> [1] 12
7.7 Minimum, maximum, étendue
min(x); max(x); range(x)#> [1] 3.72
#> [1] 483.2
#> [1] 3.72 483.20
diff(range(x)) # étendue#> [1] 479.48
7.8 Quartiles et quantiles
quantile(x, probs = c(0, 0.25, 0.5, 0.75, 1))#> 0% 25% 50% 75% 100%
#> 3.720 42.535 105.875 196.185 483.200
IQR(x) # Q3 - Q1#> [1] 153.65
summary(x)#> Min. 1st Qu. Median Mean 3rd Qu. Max.
#> 3.72 42.53 105.88 130.57 196.19 483.20
7.9 Variance et écart-type
var(x) # variance#> [1] 10963.07
sd(x) # écart-type (même unité que x)#> [1] 104.7047
L’écart-type mesure l’écart typique à la moyenne. Plus il est grand, plus les observations sont dispersées.
7.10 Distribution des variables
# Aperçu numérique
demo |>
summarise(
age_mean = mean(age),
age_sd = sd(age),
revenu_mean = mean(revenu_mensuel),
revenu_sd = sd(revenu_mensuel),
revenu_skew_approx = mean(revenu_mensuel) - median(revenu_mensuel)
)#> # A tibble: 1 × 5
#> age_mean age_sd revenu_mean revenu_sd revenu_skew_approx
#> <dbl> <dbl> <dbl> <dbl> <dbl>
#> 1 46.6 17.7 2180. 551. -11.8
Histogrammes et densités seront détaillés en Chapter 8.
7.11 Comparaison de groupes
ventes |>
group_by(region) |>
summarise(
n = n(),
ca_moyen = mean(montant),
ca_median = median(montant),
ca_sd = sd(montant),
.groups = "drop"
)#> # A tibble: 4 × 5
#> region n ca_moyen ca_median ca_sd
#> <chr> <int> <dbl> <dbl> <dbl>
#> 1 Est 50 143. 123. 120.
#> 2 Nord 47 108. 62.8 98.2
#> 3 Ouest 59 129. 108. 92.2
#> 4 Sud 42 143. 112. 109.
Comparez toujours n, tendance centrale et dispersion : deux moyennes proches avec des écarts-types très différents ne racontent pas la même histoire.
7.12 Tableaux croisés
demo |>
count(sexe, niveau_etudes) |>
pivot_wider(names_from = sexe, values_from = n, values_fill = 0)#> # A tibble: 5 × 3
#> niveau_etudes Femme Homme
#> <chr> <int> <int>
#> 1 Autre 10 9
#> 2 Bac 18 20
#> 3 Doctorat 3 5
#> 4 Licence 26 33
#> 5 Master 12 12
# Avec proportions par ligne
tab <- table(demo$sexe, demo$niveau_etudes)
prop.table(tab, margin = 1) |> round(2)#>
#> Autre Bac Doctorat Licence Master
#> Femme 0.14 0.26 0.04 0.38 0.17
#> Homme 0.11 0.25 0.06 0.42 0.15
7.13 Corrélation entre variables
# Pearson (linéaire)
cor(demo$age, demo$revenu_mensuel, use = "complete.obs")#> [1] 0.01489224
cor(mtcars$wt, mtcars$mpg)#> [1] -0.8676594
mtcars |>
select(mpg, wt, hp, disp) |>
cor() |>
round(2)#> mpg wt hp disp
#> mpg 1.00 -0.87 -0.78 -0.85
#> wt -0.87 1.00 0.66 0.89
#> hp -0.78 0.66 1.00 0.79
#> disp -0.85 0.89 0.79 1.00
Une corrélation forte indique une association statistique, pas qu’une variable cause l’autre. Un facteur tiers peut expliquer les deux.
7.14 Interprétation en langage courant
Exemple : cor(mtcars$wt, mtcars$mpg) est négatif et marqué.
Résultat observé : les voitures plus lourdes tendent à avoir une consommation en miles/gallon plus faible dans cet échantillon.
Interprétation prudente : il existe une association linéaire négative entre poids et mpg dans mtcars. Cela ne prouve pas, à elle seule, le mécanisme causal (moteur, aérodynamique, etc.).
7.15 Limites et erreurs d’interprétation
- Décrire un échantillon n’équivaut pas à conclure sur toute une population (→ inférence, Chapter 9).
- La moyenne seule cache multimodalité et outliers.
- Des catégories déséquilibrées faussent les lectures de proportions.
- Corréler deux séries temporelles sans précaution peut créer des artefacts.
- Multiplier les tris jusqu’à trouver un résultat « significatif » (data dredging).
7.16 Démonstration complète
set.seed(2024)
rapport <- list(
ca_total = sum(ventes$montant),
ca_moyen = mean(ventes$montant),
ca_median = median(ventes$montant),
top_produit = ventes |> count(produit, sort = TRUE) |> slice(1),
cor_qte_montant = cor(ventes$quantite, ventes$montant)
)
rapport#> $ca_total
#> [1] 25853.53
#>
#> $ca_moyen
#> [1] 130.5734
#>
#> $ca_median
#> [1] 105.875
#>
#> $top_produit
#> # A tibble: 1 × 2
#> produit n
#> <chr> <int>
#> 1 Marqueur 43
#>
#> $cor_qte_montant
#> [1] 0.6708037
7.17 Exercices
7.17.1 Niveau 1
- Calculez moyenne et médiane de
demo$age. - Affichez la table des effectifs de
niveau_etudes.
7.17.2 Niveau 2
- Comparez le revenu moyen et médian par
sexe. - Calculez l’IQR de
montantdansventes.
7.17.3 Niveau 3
- Produisez un tableau région × produit avec le CA total (
sum(montant)). - Interprétez en une phrase
cor(mtcars$hp, mtcars$mpg).
7.18 Corrections
mean(demo$age); median(demo$age)#> [1] 46.64189
#> [1] 47
demo |> count(niveau_etudes, sort = TRUE)#> # A tibble: 5 × 2
#> niveau_etudes n
#> <chr> <int>
#> 1 Licence 59
#> 2 Bac 38
#> 3 Master 24
#> 4 Autre 19
#> 5 Doctorat 8
demo |>
group_by(sexe) |>
summarise(moy = mean(revenu_mensuel), med = median(revenu_mensuel), .groups = "drop")#> # A tibble: 2 × 3
#> sexe moy med
#> <chr> <dbl> <dbl>
#> 1 Femme 2204. 2215
#> 2 Homme 2159. 2146
IQR(ventes$montant)#> [1] 153.65
ventes |>
group_by(region, produit) |>
summarise(ca = sum(montant), .groups = "drop") |>
pivot_wider(names_from = produit, values_from = ca, values_fill = 0)#> # A tibble: 4 × 6
#> region Agenda Cahier Classeur Marqueur Stylo
#> <chr> <dbl> <dbl> <dbl> <dbl> <dbl>
#> 1 Est 1757. 1443. 1228. 1418. 1295.
#> 2 Nord 282. 1560. 1201. 705. 1349.
#> 3 Ouest 1874. 1425. 1726. 1115. 1482.
#> 4 Sud 418. 934. 824. 2618. 1201.
cor(mtcars$hp, mtcars$mpg)#> [1] -0.7761684
# Interprétation : association linéaire négative — plus de chevaux, mpg souvent plus faible dans cet échantillon.7.19 Points clés
- Décrire = résumer sans sur-interpréter.
- Médiane et IQR sont robustes ; moyenne et écart-type sont sensibles aux extrêmes.
- Toute corrélation demande une phrase de prudence sur la causalité.
7.20 Ressources
7.21 Suite
Chapter 8 : donner forme visuelle à ces résumés avec ggplot2.