La régression logistique ordinale est une extension de la régression logistique binaire qui permet d’analyser des variables dépendantes catégorielles ordonnées ayant plus de deux niveaux. Dans notre étude, nous l’appliquons à l’analyse de la perception environnementale des véhicules électriques, un sujet d’actualité crucial dans le contexte de la transition écologique.
La régression logistique ordinale modélise la probabilité cumulée d’appartenir à une catégorie donnée ou à une catégorie inférieure. Pour une variable dépendante à K catégories ordonnées, le modèle estime (K-1) équations simultanément.
Pour une variable dépendante Y avec K catégories ordonnées (1, …, K), le modèle s’écrit :
\(logit[P(Y \leq k|x)] = \alpha_k - (\beta_1x_1 + \beta_2x_2 + ... + \beta_px_p)\)
où : - \(P(Y \leq k|x)\) est la probabilité cumulée jusqu’à la catégorie k - \(\alpha_k\) sont les intercepts pour chaque catégorie k - \(\beta_i\) sont les coefficients des variables explicatives - \(x_i\) sont les variables explicatives
Une hypothèse fondamentale est que l’effet des variables explicatives est constant à travers les différents niveaux de la variable dépendante. Cette hypothèse implique que les coefficients \(\beta\) sont les mêmes pour toutes les catégories.
# Création des données
set.seed(123)
n <- 500
donnees <- data.frame(
prix = rnorm(n, mean = 45, sd = 10),
autonomie = rnorm(n, mean = 4, sd = 0.8),
temps_recharge = rlnorm(n, log(1), 0.3),
empreinte_production = rnorm(n, mean = 7, sd = 1),
disponibilite_bornes = runif(n, 2, 9),
age = rnorm(n, mean = 45, sd = 12)
)
# Score latent avec des coefficients plus forts
score_latent <- with(donnees, {
-0.8 * scale(prix) + # Plus fort effet négatif du prix
0.9 * scale(autonomie) + # Plus fort effet positif de l'autonomie
-0.6 * scale(temps_recharge) + # Plus fort effet négatif du temps
-0.8 * scale(empreinte_production) + # Plus fort effet négatif de l'empreinte
0.6 * scale(disponibilite_bornes) + # Plus fort effet positif des bornes
-0.4 * scale(age) + # Plus fort effet de l'âge
rnorm(n, 0, 0.6) # Moins de bruit aléatoire
})
# Seuils plus équilibrés
seuils <- c(-Inf, -1.0, -0.3, 0.3, 1.0, Inf)
donnees$impact_percu <- cut(score_latent,
breaks = seuils,
labels = c("Très négatif", "Plutôt négatif", "Neutre",
"Plutôt positif", "Très positif"),
ordered = TRUE)
# Distribution de l'impact perçu
barplot(table(donnees$impact_percu),
main = "Distribution de l'impact environnemental perçu",
col = "lightblue")
# Boxplot du prix selon l'impact
boxplot(prix ~ impact_percu, data = donnees,
main = "Prix selon l'impact perçu",
xlab = "Impact perçu",
ylab = "Prix (k€)")
# Standardisation des variables
donnees_std <- donnees %>%
mutate(across(
c(prix, autonomie, temps_recharge, empreinte_production,
disponibilite_bornes, age),
scale
))
# Assurer que impact_percu est un facteur ordonné
donnees_std$impact_percu <- factor(donnees_std$impact_percu,
levels = c("Très négatif", "Plutôt négatif",
"Neutre", "Plutôt positif", "Très positif"),
ordered = TRUE)
# Ajustement du modèle
modele <- polr(impact_percu ~ prix + autonomie + temps_recharge +
empreinte_production + disponibilite_bornes + age,
data = donnees_std, method = "logistic")
# Résumé du modèle
summary(modele)
##
## Réajustement pour obtenir le Hessien
## Call:
## polr(formula = impact_percu ~ prix + autonomie + temps_recharge +
## empreinte_production + disponibilite_bornes + age, data = donnees_std,
## method = "logistic")
##
## Coefficients:
## Value Std. Error t value
## prix -2.347 0.1672 -14.04
## autonomie 2.867 0.1887 15.19
## temps_recharge -1.799 0.1482 -12.14
## empreinte_production -2.376 0.1661 -14.31
## disponibilite_bornes 1.886 0.1467 12.85
## age -1.377 0.1321 -10.42
##
## Intercepts:
## Value Std. Error t value
## Très négatif|Plutôt négatif -3.2294 0.2309 -13.9882
## Plutôt négatif|Neutre -0.8807 0.1640 -5.3705
## Neutre|Plutôt positif 0.8520 0.1650 5.1629
## Plutôt positif|Très positif 2.9561 0.2239 13.2022
##
## Residual Deviance: 758.3983
## AIC: 778.3983
# Récupération des coefficients (sans les seuils)
coef_vars <- coef(modele)[1:6] # Uniquement les coefficients des variables
se_vars <- sqrt(diag(vcov(modele)))[1:6] # Leurs erreurs standards
##
## Réajustement pour obtenir le Hessien
# Création du tableau des résultats
resultats <- data.frame(
Variable = names(coef_vars),
Coefficient = coef_vars,
Std.Error = se_vars,
Odds_Ratio = exp(coef_vars),
OR_lower = exp(coef_vars - 1.96 * se_vars),
OR_upper = exp(coef_vars + 1.96 * se_vars)
)
# Affichage des résultats
print(resultats)
## Variable Coefficient Std.Error Odds_Ratio
## prix prix -2.347269 0.1671748 0.09562992
## autonomie autonomie 2.866846 0.1886820 17.58148004
## temps_recharge temps_recharge -1.799431 0.1482106 0.16539298
## empreinte_production empreinte_production -2.376268 0.1660697 0.09289666
## disponibilite_bornes disponibilite_bornes 1.885583 0.1467346 6.59019424
## age age -1.377488 0.1321347 0.25221120
## OR_lower OR_upper
## prix 0.06891150 0.1327076
## autonomie 12.14635849 25.4486512
## temps_recharge 0.12369658 0.2211447
## empreinte_production 0.06708705 0.1286357
## disponibilite_bornes 4.94305273 8.7862021
## age 0.19466553 0.3267681
# Visualisation des odds ratios
ggplot(resultats, aes(x = Variable, y = Odds_Ratio)) +
geom_point() +
geom_errorbar(aes(ymin = OR_lower, ymax = OR_upper), width = 0.2) +
coord_flip() +
geom_hline(yintercept = 1, linetype = "dashed", color = "red") +
labs(title = "Odds Ratios avec Intervalles de Confiance",
y = "Odds Ratio") +
theme_minimal()
Interprétation des Odds Ratios :
OR > 1 : effet positif sur la perception OR < 1 : effet négatif sur la perception OR = 1 : pas d’effet
Par exemple, pour le prix :
OR = 0.096 Interprétation : Une augmentation d’une unité standardisée du prix multiplie par 0.096 les chances d’avoir une perception plus positive
Les résultats du modèle montrent que :
Autonomie (OR = 17.581) : L’effet le plus positif. Une augmentation d’une unité standardisée de l’autonomie multiplie par 17.6 les chances d’avoir une perception plus positive.
Empreinte production (OR = 0.096) : Impact très négatif. Une augmentation d’une unité de l’empreinte carbone réduit de 90.4% les chances d’une perception positive.
Disponibilité bornes (OR = 6.590) : Impact positif significatif. Une meilleure disponibilité des bornes multiplie par 6.6 les chances d’une perception positive.
Temps recharge (OR = 0.165) : Impact négatif. Une augmentation du temps de recharge réduit de 83.5% les chances d’une perception positive.
Prix (OR = 0.093) : Impact très négatif. Une augmentation du prix réduit de 90.7% les chances d’une perception positive.
Age (OR = 0.252) : Impact négatif modéré. Une augmentation de l’âge réduit de 74.8% les chances d’une perception positive.
# Prédictions
predictions <- predict(modele, donnees_std, type = "class")
# Table de confusion
table_confusion <- table(predictions, donnees_std$impact_percu)
print(table_confusion)
##
## predictions Très négatif Plutôt négatif Neutre Plutôt positif Très positif
## Très négatif 117 18 2 0 0
## Plutôt négatif 15 43 23 6 0
## Neutre 3 15 16 16 4
## Plutôt positif 1 4 20 29 18
## Très positif 0 2 3 19 126
# Calcul de l'accuracy
accuracy <- sum(diag(table_confusion)) / sum(table_confusion)
print(paste("Précision du modèle:", round(accuracy, 3)))
## [1] "Précision du modèle: 0.662"
La matrice de confusion révèle que :
# Créer un résumé des effets principaux
resultats_synthese <- data.frame(
Variable = c("Empreinte production", "Autonomie", "Disponibilité bornes",
"Prix", "Temps recharge", "Age"),
Impact = c("Très négatif", "Très positif", "Positif",
"Négatif", "Négatif", "Légèrement négatif"),
Odds_Ratio = exp(coef(modele)[1:6])
)
# Afficher le tableau de synthèse
knitr::kable(resultats_synthese,
caption = "Synthèse des effets des variables",
digits = 3)
| Variable | Impact | Odds_Ratio | |
|---|---|---|---|
| prix | Empreinte production | Très négatif | 0.096 |
| autonomie | Autonomie | Très positif | 17.581 |
| temps_recharge | Disponibilité bornes | Positif | 0.165 |
| empreinte_production | Prix | Négatif | 0.093 |
| disponibilite_bornes | Temps recharge | Négatif | 6.590 |
| age | Age | Légèrement négatif | 0.252 |
# Graphique de synthèse des effets
ggplot(resultats_synthese, aes(x = reorder(Variable, Odds_Ratio), y = Odds_Ratio)) +
geom_bar(stat = "identity", fill = "skyblue") +
geom_hline(yintercept = 1, linetype = "dashed", color = "red") +
coord_flip() +
labs(title = "Impact relatif des variables sur la perception",
x = "Variables",
y = "Odds Ratio") +
theme_minimal()
Basées sur notre analyse, voici les principales recommandations :