# -*- coding: utf-8 -*- """ depouiller_pretest.py — MOD Focus marketing avancé / Expérimentation (2026-2027) Le pré-test répond à UNE question : la manipulation est-elle perçue ? Porté en pandas depuis « pre-test AV3.Rmd » (dépouillement des stimuli d'une étude 2×2) et « AV3 process.Rmd » (t.test(MC ~ condition)). Trente personnes hors cible suffisent : on ne teste pas l'hypothèse, on teste le stimulus. Entrée : un CSV avec une ligne par répondant et au moins les colonnes flow (A/B), les items du MC (mc1, mc2…), attention. Si vous partez de l'export brut de collect.php, passez d'abord par analyse_campagne.charger_events() qui produit ce format. Décision : - MC significatif dans le sens attendu -> stimuli validés, on lance. - MC non significatif -> on corrige la CRÉA (la différence est-elle visible ? unique ? assez forte ?), pas l'hypothèse. On re-pré-teste. - attention check raté par > 20 % -> la différence n'est même pas vue : trop discrète. """ import math import pandas as pd from scipy import stats FICHIER = "exemple_pretest.csv" MC_ITEMS = ["mc1", "mc2"] ATTENTION_OK = {"A": "acte", "B": "abonnement"} # la bonne réponse attendue par condition SENS_ATTENDU = "B > A" # ce que prédit votre manipulation sur le MC df = pd.read_csv(FICHIER) for c in MC_ITEMS: df[c] = pd.to_numeric(df[c], errors="coerce") df["MC"] = df[MC_ITEMS].mean(axis=1) print("Répondants : %d (A = %d, B = %d)" % (len(df), (df.flow == "A").sum(), (df.flow == "B").sum())) # 1. Attention check : la différence a-t-elle été VUE ? if "attention" in df.columns: df["attention_ok"] = df.apply(lambda r: r["attention"] == ATTENTION_OK.get(r["flow"]), axis=1) taux = df.groupby("flow")["attention_ok"].mean() * 100 print("\nAttention check réussi : A = %.0f %%, B = %.0f %%" % (taux.get("A", float("nan")), taux.get("B", float("nan")))) if (100 - taux).max() > 20: print(" ! Plus de 20 %% d'échec dans une condition : la différence est trop discrète ou la page trop longue.") # 2. Moyennes item par item (comme le script AV3 triait les plats) — repère l'item qui ne marche pas print("\nMoyennes par item et par condition :") print(df.groupby("flow")[MC_ITEMS + ["MC"]].agg(["mean", "std"]).round(2).to_string()) # 3. Le test : Welch sur le score MC a = df.loc[df.flow == "A", "MC"].dropna() b = df.loc[df.flow == "B", "MC"].dropna() t, p = stats.ttest_ind(a, b, equal_var=False) va, vb = a.var(ddof=1) / len(a), b.var(ddof=1) / len(b) ddl = (va + vb) ** 2 / (va ** 2 / (len(a) - 1) + vb ** 2 / (len(b) - 1)) sp = math.sqrt(((len(a) - 1) * a.var(ddof=1) + (len(b) - 1) * b.var(ddof=1)) / (len(a) + len(b) - 2)) d = (a.mean() - b.mean()) / sp if sp else float("nan") print("\nMC : A M = %.2f (SD = %.2f, n = %d) | B M = %.2f (SD = %.2f, n = %d)" % (a.mean(), a.std(ddof=1), len(a), b.mean(), b.std(ddof=1), len(b))) print("t(%.1f) = %.2f, %s, d = %.2f" % (ddl, t, ("p < .001" if p < 0.001 else "p = %.3f" % p), d)) bon_sens = (b.mean() > a.mean()) if SENS_ATTENDU == "B > A" else (a.mean() > b.mean()) if p < 0.05 and bon_sens: print("\n-> Manipulation perçue dans le sens attendu : stimuli validés. Lancez la campagne avec CES créas, sans les retoucher.") elif p < 0.05: print("\n-> Manipulation perçue… dans le sens INVERSE : relisez votre MC (échelle inversée ?) ou votre créa.") else: print("\n-> Manipulation NON perçue : on corrige la créa (différence plus visible, plus forte, unique), pas l'hypothèse." " Nouveau pré-test avant tout lancement — « si le pré-test n'est pas satisfaisant, vous avez collecté pour rien ».")