Vous faites partie d’un groupe de recherche qui a pour objectif d’identifier les dĂ©terminants de l’intention des consommateurs de payer une chambre d’hĂŽtel en cryptomonnaie.
AprÚs avoir mené une revue de littérature, votre équipe souhaite tester le modÚle suivant :

L’opĂ©rationnalisation des concepts a Ă©tĂ© rĂ©alisĂ©e en utilisant les items prĂ©sentĂ©s dans le tableau suivant :

A partir des donnĂ©es collectĂ©es dans le fichier “BASE-Voyage-BTC”, votre travail consiste Ă :
- vérifier la structure factorielle de chaque mesure
- vérifier la fiabilité de chaque mesure
- tester le modĂšle thĂ©orique en utilisant la mĂ©thode qui vous semble appropriĂ©e (rĂ©gression multiple, modĂšle PLS, modĂšle d’Ă©quations structurelles …)
Le fichier à télécharger
Exemple de test de l’Ă©chelle de mesure de la Norme Subjective :
Installer les bibliothĂšques
!pip install factor_analyzer
!pip install --upgrade scikit-learn
!pip install --upgrade --no-deps scikit-learn
!pip install --upgrade imbalanced-learn xgboost
Lire les données
import pandas as pd
# Charger le fichier Excel dans un DataFrame
data_original = pd.read_excel('/content/BASE-Voyage-BTC_OK.xlsx')
RĂ©aliser l’ACP
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.preprocessing import StandardScaler
from factor_analyzer import FactorAnalyzer
from factor_analyzer.factor_analyzer import calculate_kmo, calculate_bartlett_sphericity
from ipywidgets import interactive
import ipywidgets as widgets
# Fonction pour calculer l'alpha de Cronbach
def cronbach_alpha(df):
if len(df.columns) > 1:
k = df.shape[1]
variances = df.var(axis=0, ddof=1)
total_variance = df.sum(axis=1).var(ddof=1)
return (k / (k - 1)) * (1 - (variances.sum() / total_variance))
else:
print("â ïž Pas assez de variables pour calculer l'alpha sans item.")
# Chargement des données (supposées déjà chargées dans data_original)
def select_columns(data):
print("\nColonnes disponibles :", list(data.columns))
selected_columns = input("Entrez les noms des colonnes pour l'ACP (séparées par une virgule) : ").strip().split(',')
selected_columns = [col.strip() for col in selected_columns]
if not all(col in data.columns for col in selected_columns):
print("Erreur : certaines colonnes n'existent pas. RĂ©essayez.")
return select_columns(data)
return selected_columns
# Ătape 1 : SĂ©lection des colonnes pour l'ACP
selected_columns = select_columns(data_original)
df = data_original[selected_columns]
# Ătape 2 : Normalisation des donnĂ©es
scaler = StandardScaler()
data_scaled = scaler.fit_transform(df)
# Ătape 3 : Test KMO et Bartlett
kmo_all, kmo_model = calculate_kmo(df)
chi_square_value, p_value = calculate_bartlett_sphericity(df)
print(f"\nKMO global : {kmo_model:.3f}")
print(f"Test de Bartlett : ChiÂČ = {chi_square_value:.3f}, p = {p_value:.3f}")
# Ătape 4 : CommunalitĂ©s
# Affichage des communalités
fa_temp = FactorAnalyzer(rotation=None, method='principal', is_corr_matrix=False)
fa_temp.fit(data_scaled)
eigenvalues, _ = fa_temp.get_eigenvalues()
n_factors = sum(eigenvalues > 1)
print(f"Nombre de composantes retenues (valeurs propres > 1) : {n_factors}")
fa_temp = FactorAnalyzer(rotation=None, method='principal', n_factors=n_factors,is_corr_matrix=False)
fa_temp.fit(data_scaled)
communalities = pd.DataFrame({
'Variable': df.columns,
'Initial': [1.000] * len(df.columns), # Les valeurs initiales sont toujours 1
'Communalité': fa_temp.get_communalities()
}).round(3)
print("\nCommunalités des variables:")
print(communalities)
# Ătape 5 : DĂ©termination du nombre de facteurs
eigenvalues, _ = fa_temp.get_eigenvalues()
n_factors = sum(eigenvalues > 1)
print(f"Nombre de composantes retenues (valeurs propres > 1) : {n_factors}")
# Tableau des variances expliquées
explained_variance_ratio = eigenvalues / np.sum(eigenvalues)
cumulative_variance = np.cumsum(explained_variance_ratio)
variance_table = pd.DataFrame({
'Composante': [f"Composante {i+1}" for i in range(len(eigenvalues))],
'Valeurs propres': eigenvalues,
'Variance expliquée (%)': explained_variance_ratio * 100,
'Variance expliquée cumulée (%)': cumulative_variance * 100
}).round(3)
display(variance_table)
# Graphique Scree Plot
plt.figure(figsize=(8, 6))
plt.plot(range(1, len(eigenvalues) + 1), eigenvalues, marker='o')
plt.title("Graphique des valeurs propres (Scree Plot)")
plt.xlabel("Composantes")
plt.ylabel("Valeurs propres")
plt.grid(True)
plt.show()
# Ătape 6 : Choix du nombre de facteurs par l'utilisateur
# Demander Ă l'utilisateur le nombre de composantes Ă retenir au moment de la sauvegarde
n_factors = int(input("Entrez le nombre de composantes Ă retenir pour les scores factoriels : "))
# Ătape 7 : Analyse factorielle avec le nombre de facteurs sĂ©lectionnĂ©
fa = FactorAnalyzer(rotation=None, method='principal', n_factors=n_factors)
fa.fit(data_scaled)
# Matrice des charges factorielles
loadings = fa.loadings_
components_matrix = pd.DataFrame(loadings, index=df.columns).round(3)
display(components_matrix)
# Ătape 8 : Cercle des corrĂ©lations
if n_factors > 1:
fig, ax = plt.subplots(figsize=(6, 6))
ax.set_xlim(-1, 1)
ax.set_ylim(-1, 1)
ax.axhline(0, color='black', linestyle='-', linewidth=0.8)
ax.axvline(0, color='black', linestyle='-', linewidth=0.8)
ax.grid(True, linestyle='--', linewidth=0.5, alpha=0.7)
for i in range(loadings.shape[0]):
ax.scatter(loadings[i, 0], loadings[i, 1], color='b', alpha=0.5, s=50)
ax.text(loadings[i, 0], loadings[i, 1], df.columns[i], color='r', fontsize=8, ha='center')
ax.set_title("Cercle des corrélations", fontsize=10)
ax.set_xlabel("Composante 1")
ax.set_ylabel("Composante 2")
plt.show()
# Demander Ă l'utilisateur s'il souhaite une rotation
rotation_choice = input("Souhaitez-vous procéder à une rotation des variables ? (oui/non) : ").strip().lower()
if rotation_choice == "non":
fa = FactorAnalyzer(n_factors=n_factors, rotation=None, method='principal')
fa.fit(data_scaled)
factor_scores = fa.transform(data_scaled)
# Demander Ă l'utilisateur le nom des composantes
component_names = []
for i in range(n_factors):
name = input(f"Entrez le nom pour la composante {i+1} : ")
component_names.append(name)
components_matrix.columns = component_names
factor_scores_df = pd.DataFrame(factor_scores, columns=component_names)
# Affichage des scores factoriels
display(factor_scores_df)
# Calcul de l'alpha de cronbach
global_alpha = cronbach_alpha(df)
print(f"Alpha de Cronbach global : {global_alpha:.3f}")
if len(df.columns) > 1:
alpha_sans_item = {col: cronbach_alpha(df.drop(columns=[col])) for col in df.columns}
df_alpha = pd.DataFrame.from_dict(alpha_sans_item, orient='index', columns=['Alpha sans item']).round(3)
display(df_alpha)
else:
print("â ïž Pas assez de variables pour calculer l'alpha sans item.")
############# ROTATION ##################@@
else:
rotation_types = ["varimax", "promax", "oblimin", "quartimax"]
print("Types de rotation disponibles :", rotation_types)
rotation_type = input("Veuillez entrer le type de rotation souhaité : ").strip().lower()
if rotation_type not in rotation_types:
print("Type de rotation non valide. Par défaut, 'varimax' sera utilisé.")
rotation_type = "varimax"
fa = FactorAnalyzer(n_factors=n_factors, rotation=rotation_type, method='principal')
fa.fit(data_scaled)
loadings = fa.loadings_
components_matrix = pd.DataFrame(loadings, index=df.columns).round(3)
# Affichage des scores factoriels
# display(factor_scores_df)
# Ătape 8 : Cercle des corrĂ©lations
if n_factors > 1:
fig, ax = plt.subplots(figsize=(6, 6))
ax.set_xlim(-1, 1)
ax.set_ylim(-1, 1)
ax.axhline(0, color='black', linestyle='-', linewidth=0.8)
ax.axvline(0, color='black', linestyle='-', linewidth=0.8)
ax.grid(True, linestyle='--', linewidth=0.5, alpha=0.7)
for i in range(loadings.shape[0]):
ax.scatter(loadings[i, 0], loadings[i, 1], color='b', alpha=0.5, s=50)
ax.text(loadings[i, 0], loadings[i, 1], df.columns[i], color='r', fontsize=8, ha='center')
ax.set_title("Cercle des corrélations", fontsize=10)
ax.set_xlabel("Composante 1")
ax.set_ylabel("Composante 2")
plt.show()
# Demander Ă l'utilisateur le nom des composantes
component_names = []
for i in range(n_factors):
name = input(f"Entrez le nom pour la composante {i+1} : ")
component_names.append(name)
components_matrix.columns = component_names
factor_scores = fa.transform(data_scaled)
factor_scores_df = pd.DataFrame(factor_scores, columns=component_names)
# Affichage des scores factoriels
display(factor_scores_df)
global_alpha = cronbach_alpha(df)
print(f"Alpha de Cronbach global : {global_alpha:.3f}")
if len(df.columns) > 1:
alpha_sans_item = {col: cronbach_alpha(df.drop(columns=[col])) for col in df.columns}
df_alpha = pd.DataFrame.from_dict(alpha_sans_item, orient='index', columns=['Alpha sans item']).round(3)
display(df_alpha)
else:
print("â ïž Pas assez de variables pour calculer l'alpha sans item.")
#else:
# print("Le calcul de l'alpha de Cronbach n'a pas été demandé.")
# Demander à l'utilisateur s'il souhaite enregistrer les résultats
def save_results():
global data_original
data_original = pd.concat([data_original, factor_scores_df], axis=1)
output_file = "Analyse_Factorielle_Resultats.xlsx"
with pd.ExcelWriter(output_file) as writer:
factor_scores_df.to_excel(writer, sheet_name="Scores_Factoriels", index=False)
df_alpha.to_excel(writer, sheet_name="Alpha_Cronbach", index=True)
print(f"\nLes résultats ont été sauvegardés dans {output_file}.")
save_btn = widgets.Button(description="Enregistrer les résultats")
save_btn.on_click(lambda b: save_results())
display(save_btn)
RĂ©gression
import pandas as pd
import numpy as np
import statsmodels.api as sm
import matplotlib.pyplot as plt
import seaborn as sns
from sklearn.preprocessing import StandardScaler
from statsmodels.stats.outliers_influence import variance_inflation_factor
# Sélectionner les variables explicatives (X) et la variable dépendante (y)
y_var = input("Entrez le nom de la variable dépendante : ").strip()
X_vars = input("Entrez les noms des variables explicatives (séparés par une virgule) : ").strip().split(",")
# VĂ©rification des variables
if y_var not in data_original.columns or any(var not in data_original.columns for var in X_vars):
raise ValueError("Erreur : Assurez-vous que toutes les variables existent dans le DataFrame.")
# DĂ©finir X et y
X = data_original[X_vars] # Suppression de l'ajout de la constante
y = data_original[y_var]
# VĂ©rifier si X contient au moins une variable
if X.shape[1] == 0:
raise ValueError("Erreur : Aucune variable explicative valide sélectionnée.")
# Ajustement du modĂšle OLS
model = sm.OLS(y, X).fit()
print(model.summary())
# Vérification de la normalité des résidus avec un QQ-plot
residuals = model.resid
fig, ax = plt.subplots(figsize=(6, 6))
sm.qqplot(residuals, line="s", ax=ax)
ax.set_title("QQ-Plot des résidus")
plt.show()
# Vérification de l'hétéroscédasticité avec un scatter plot
plt.figure(figsize=(8, 5))
sns.scatterplot(x=model.fittedvalues, y=residuals)
plt.axhline(0, linestyle="dashed", color="red")
plt.xlabel("Valeurs ajustées")
plt.ylabel("RĂ©sidus")
plt.title("Graphique des résidus")
plt.show()
# Calcul du VIF pour détecter la multicolinéarité
if X.shape[1] > 1: # VĂ©rifier que le VIF peut ĂȘtre calculĂ©
vif_data = pd.DataFrame({
"Variable": X.columns,
"VIF": [variance_inflation_factor(X.values, i) for i in range(X.shape[1])]
})
print("\nđ Facteur d'inflation de la variance (VIF) :")
display(vif_data)
# Interprétation du VIF
high_vif = vif_data[vif_data["VIF"] > 10]
if not high_vif.empty:
print("\nâ ïž Attention : Certaines variables prĂ©sentent une forte multicolinĂ©aritĂ© (VIF > 10). Cela peut affecter la fiabilitĂ© des coefficients estimĂ©s.")
print(high_vif)
else:
print("â
Aucune multicolinéarité préoccupante détectée (VIF < 10).")
else:
print("\nâ ïž Pas assez de variables pour calculer le VIF.")
# Test de normalité des résidus (Jarque-Bera)
jb_stat, jb_pvalue, skew, kurtosis = sm.stats.jarque_bera(residuals)
print("\nđ RĂ©sultats du Test de normalitĂ© de Jarque-Bera :")
print(f" - Statistique JB : {jb_stat:.3f}")
print(f" - p-value : {jb_pvalue:.5f}")
print(f" - Asymétrie (Skewness) : {skew:.3f}")
print(f" - Aplatissement (Kurtosis) : {kurtosis:.3f}")
# Interprétation automatique
test_result = "â
Les rĂ©sidus suivent une loi normale (p > 0.05)." if jb_pvalue > 0.05 else "â Les rĂ©sidus ne suivent PAS une loi normale (p †0.05)."
print(f"\n{test_result}")
if jb_pvalue <= 0.05:
if abs(skew) > 1:
print("đ ProblĂšme dĂ©tectĂ© : **AsymĂ©trie Ă©levĂ©e** (skewness).")
print("â
Solution : Essayez une transformation logarithmique ou une normalisation.")
if kurtosis < 2 or kurtosis > 4:
print("đ ProblĂšme dĂ©tectĂ© : **Aplatissement anormal (kurtosis).**")
print("â
Solution : VĂ©rifiez s'il y a des valeurs aberrantes (outliers).")
print("\nđ Recommandations supplĂ©mentaires :")
print(" - Vérifiez la présence de valeurs aberrantes avec un boxplot.")
print(" - Testez une transformation (log, carré, racine) sur la variable dépendante.")
print(" - Ajoutez Ă©ventuellement d'autres variables explicatives.")
# Conclusion générale
print("\nđ **Conclusion** :")
print(" - L'ajustement du modĂšle est Ă©valuĂ© avec le RÂČ et le RÂČ ajustĂ©.")
print(" - Un RÂČ Ă©levĂ© (>0.7) indique une bonne capacitĂ© explicative du modĂšle, tandis qu'un RÂČ faible suggĂšre un ajustement limitĂ©.")
print(" - Les coefficients et leurs p-values indiquent la significativité des variables explicatives : une p-value < 0.05 signifie que la variable a un impact significatif.")
print(" - Le VIF aide à détecter la multicolinéarité, qui peut biaiser les estimations.")
print(" - Le test de Jarque-Bera vérifie la normalité des résidus, influençant la validité des tests de significativité.")