Exercices - Module 08

Préparation

Le cas de transfert utilise des ventes influencées par des promotions et le prix. La question n’est plus seulement de détecter une saison, mais de vérifier si le motif saisonnier demeure après la prise en compte de variables commerciales.

Ce cas prolonge la régression multiple déjà pratiquée et prépare le module 09. Les variables prix et promotion ne doivent pas être interprétées comme des causes démontrées. L’exploration et l’ajustement ci-dessous utilisent l’apprentissage; les douze derniers mois restent réservés à la comparaison.

Jeu de données de transfert : ventes_promotions_quebec.csv.

library(tidyverse)
library(broom)

data_path <- if (file.exists("../semaine-09-variables-externes-autocorrelation/data/ventes_promotions_quebec.csv")) {
  "../semaine-09-variables-externes-autocorrelation/data/ventes_promotions_quebec.csv"
} else {
  "modules/semaine-09-variables-externes-autocorrelation/data/ventes_promotions_quebec.csv"
}

ventes <- read_csv(
  data_path,
  show_col_types = FALSE
) |>
  mutate(
    date = as.Date(date),
    mois = factor(mois),
    promotion = factor(promotion)
  ) |>
  arrange(date)

entrainement <- ventes |> slice_head(n = nrow(ventes) - 12)
test <- ventes |> slice_tail(n = 12)

Exercice 1 - Isoler la tendance

Ajustez d’abord un modèle avec tendance, promotion et prix, mais sans mois. Examinez les résidus par mois de calendrier.

modele_sans_saison <- lm(
  ventes ~ tendance + promotion + prix_moyen,
  data = entrainement
)

augment(modele_sans_saison, data = entrainement) |>
  group_by(mois) |>
  summarise(
    residu_moyen = mean(.resid),
    residu_median = median(.resid),
    .groups = "drop"
  ) |>
  ggplot(aes(x = mois, y = residu_moyen, group = 1)) +
  geom_hline(yintercept = 0, linetype = "dashed") +
  geom_line(colour = "#0B4F6C") +
  geom_point(colour = "#0B4F6C") +
  labs(x = "Mois", y = "Résidu moyen") +
  theme_minimal(base_size = 12)

Repérez les mois systématiquement sous-prévus ou sur-prévus. Expliquez pourquoi ce motif soutient l’ajout d’une composante de calendrier.

Exercice 2 - Interpréter une saison

Comparez les coefficients mensuels d’un modèle sans variables commerciales et d’un modèle qui contrôle la promotion et le prix.

entrainement <- entrainement |>
  mutate(mois = relevel(mois, ref = "1"))

test <- test |>
  mutate(mois = factor(mois, levels = levels(entrainement$mois)))

modele_calendrier <- lm(
  ventes ~ tendance + mois,
  data = entrainement
)

modele_complet <- lm(
  ventes ~ tendance + mois + promotion + prix_moyen,
  data = entrainement
)

bind_rows(
  tidy(modele_calendrier) |> mutate(modele = "Calendrier"),
  tidy(modele_complet) |> mutate(modele = "Calendrier et contexte")
) |>
  filter(term %in% c("mois7", "mois12")) |>
  select(modele, term, estimate, std.error)

Interprétez décembre par rapport à janvier et expliquez pourquoi le coefficient peut changer lorsque promotion et prix sont ajoutés.

Exercice 3 - Tester le modèle

Réservez les douze derniers mois. Comparez les deux modèles et calculez la MAE séparément pour les mois avec et sans promotion.

La comparaison avec prix et promotion utilise ici leurs valeurs observées dans le bloc de validation : elle est conditionnelle à ce contexte. Pour une prévision émise avant ces mois, il faudrait des prix et promotions déjà planifiés, prévus ou scénarisés, sans utiliser rétroactivement une information inconnue à l’origine.

modele_test_calendrier <- lm(
  ventes ~ tendance + mois,
  data = entrainement
)

modele_test_complet <- lm(
  ventes ~ tendance + mois + promotion + prix_moyen,
  data = entrainement
)

evaluation <- bind_rows(
  test |>
    transmute(
      promotion,
      observe = ventes,
      prevision = predict(modele_test_calendrier, newdata = test),
      modele = "Calendrier"
    ),
  test |>
    transmute(
      promotion,
      observe = ventes,
      prevision = predict(modele_test_complet, newdata = test),
      modele = "Calendrier et contexte"
    )
)

evaluation |>
  group_by(modele, promotion) |>
  summarise(
    observations = n(),
    MAE = mean(abs(observe - prevision)),
    biais = mean(observe - prevision),
    .groups = "drop"
  )

Choisissez un modèle en considérant la stabilité entre les deux types de mois, et non seulement la moyenne globale.

Exercice de synthèse

Rédigez une note expliquant ce qui relève de la tendance, du calendrier et du contexte commercial. Ajoutez le résultat hors échantillon, une limite causale et une règle de mise à jour lorsque le plan de promotion change.

Assistant IA Ouvrir le GPT du cours