A/B-Test
Kurz gesagt: Ein A/B-Test vergleicht zwei Varianten an zufällig aufgeteilten Besuchern und prüft, ob der Abstand in der Konversion echt oder nur Rauschen ist.
Problem
„Ist der neue Warenkorb besser?“
Das Team hat eine neue Warenkorbseite gebaut: kürzer, mit weniger Feldern. Niemand weiß, ob sie besser ist. Also sieht zwei Wochen lang jeder Besuch der Seite zufällig entweder den alten (old) oder den neuen (new) Warenkorb. Die Spalte ordered ist 1, wenn der Besuch mit einer Bestellung endet:
Das ist ein A/B-Test: zwei Versionen, zufällig aufgeteilte Besucher, ein Maß. Das Maß ist hier die Konversion: der Anteil der Besuche, die mit einer Bestellung enden. Der alte Warenkorb hat 3,10 %, der neue 3,72 %.
Der Abstand ist 0,62 Prozentpunkte: eine Differenz zwischen zwei Prozentwerten. Das sind etwa ein Fünftel mehr Bestellungen. Aber ist es Rauschen?
Die Idee
Ist der Abstand Rauschen?
Das ist die Frage aus der Lektion über Hypothesen. Die Nullhypothese: Der Warenkorb macht keinen Unterschied. Stimmt sie, spielen die Labels old und new keine Rolle, und du kannst sie mischen. Wie oft geben die gemischten Daten einen Abstand von mindestens 0,62 Punkten?
Bei 2.000 Mischungen ist der größte Abstand 0,76 Punkte, aber nur 6-mal ist er mindestens so groß wie der echte. p ist 0,003. Ein solcher Abstand kommt selten vom Rauschen.
Genauer, für Neugierige
ordered ist 0 oder 1, also ist der Mittelwert der Spalte genau der Anteil der Bestellungen. Das Mischen ist hier eine Schleife: Die Tabelle hat 28.176 Zeilen, und 2.000 Mischungen auf einmal in einer Matrix würden im Browser viel Speicher brauchen.
Probier es aus
Auf jedem Gerät?
Kommt der Zuwachs von Handys oder von Desktops? Speichere in rates die Konversion in Prozent für jedes Gerät (Zeilen) und jede Variante (Spalten) und in lift die Differenz new − old für jedes Gerät, in Punkten.
Lösung
import pandas as pd
visits = pd.read_csv('ab_visits.csv')
rates = visits.pivot_table(index='device', columns='variant', values='ordered', aggfunc='mean') * 100
lift = rates['new'] - rates['old']
print(rates.round(2))
print(lift.round(2))visits.pivot_table(index='device', columns='variant', values='ordered', aggfunc='mean') * 100 gibt eine 2 × 2-Tabelle. Auf dem Desktop ist die Konversion 4,20 % mit dem alten Warenkorb und 5,26 % mit dem neuen, auf dem Handy 2,51 % und 2,90 %. Den Zuwachs gibt es auf beiden Geräten: 1,05 und 0,39 Punkte. Mit der Spalte revenue würdest du den Umsatz pro Besuch berechnen, nicht die Konversion.
Die Idee
Der schnellere Weg: chi2_contingency
Für zwei Anteile gibt es eine fertige Prüfung. Zuerst zählt pd.crosstab die Paare: wie viele Besuche jeder Variante eine Bestellung haben und wie viele nicht. Dann sagt scipy.stats.chi2_contingency, wie selten eine solche Tabelle ist, wenn die Variante keinen Unterschied macht:
p ist 0,0046, also etwa 0,005. Das Mischen gab 0,003: Beide Wege sagen dasselbe. Der kleine Unterschied entsteht, weil 2.000 Mischungen p nur grob messen (6 Fälle) und chi2_contingency bei einer 2 × 2-Tabelle eine kleine Korrektur macht, die p leicht anhebt.
Die Idee
Wie groß ist der Zuwachs?
p sagt nur „kaum Rauschen“. Der Chef fragt etwas anderes: Wie viel besser ist der neue Warenkorb? Dafür brauchst du ein Intervall. Wie in der Lektion über Intervalle ziehst du aus jeder Gruppe neue Stichproben mit Zurücklegen und beobachtest, wie sich der Abstand ändert:
Der Zuwachs ist 0,62 Punkte, und das 95-%-Intervall reicht von 0,21 bis 1,04 Punkten. Null liegt außerhalb des Intervalls: Das ist dasselbe „kaum Rauschen“. Aber das Intervall sagt auch, wie viel: Es kann knapp über 0,2 sein, es kann über 1 Punkt sein.
Genauer, für Neugierige
Hier sind es 2.000 Wiederholungen, nicht 10.000, damit es schnell läuft: Jede zieht 14.000 Zeilen. Nach der Formel ist das Intervall einer Differenz zwischen zwei Anteilen die Differenz ± 1,96 × √(p₁(1 − p₁)/n₁ + p₂(1 − p₂)/n₂). Sie gibt fast dasselbe:
Die Idee
Wie viele Besuche du brauchst
Wie lange soll der Test laufen? Das entscheidest du bevor du anfängst, aus zwei Zahlen: der bisherigen Konversion (3,1 %) und dem kleinsten Zuwachs, der für dich zählt (0,6 Punkte). Es gibt eine Faustregel für eine Chance von 80 %, den Zuwachs bei der Schwelle 0,05 zu sehen:
Besuche pro Gruppe ≈ 16 × p × (1 − p) / Zuwachs²
Du brauchst 13.351 Besuche pro Gruppe, insgesamt 26.701. Die Chance, dass der Test einen echten Zuwachs erkennt, heißt Teststärke (Power). Du kannst sie mit einer Simulation prüfen: Denk dir 2.000 Tests mit Konversionen von 3,1 % und 3,7 % aus und zähle, wie oft p unter 0,05 herauskommt. rng.binomial(n, 0.031) gibt, wie viele Bestellungen aus n Besuchen kommen, jeder mit einer Chance von 3,1 %:
Mit 2.000 Besuchen pro Gruppe erkennt der Test den Zuwachs nur in 18 % der Fälle, mit 5.000 in 37 %. Mit 13.351 sind es 78 %, nah an den 80 % der Regel. Ein kleiner Test sagt nicht „kein Unterschied“: Er kann ihn nur nicht sehen.
Genauer, für Neugierige
p_value ist die Prüfung zweier Anteile per Formel (ein z-Test). Sie arbeitet auf ganzen Arrays auf einmal, sodass 2.000 Tests einen Moment dauern. Für eine 2 × 2-Tabelle gibt sie fast dasselbe wie chi2_contingency. Die 16 in der Regel kommt aus der Schwelle 0,05 und 80 % Teststärke: (1,96 + 0,84)² × 2 ≈ 16.
Probier es aus
Ein größerer Zuwachs
Das Produktteam sagt: „Uns interessiert nur ein Zuwachs von mindestens 1 Punkt.“ Wie viele Besuche pro Gruppe braucht die Regel? Speichere sie als ganze Zahl in per_group.
Lösung
base = 0.031
lift = 0.01
per_group = round(16 * base * (1 - base) / lift ** 2)
print(per_group)round(16 * 0.031 * (1 - 0.031) / 0.01 ** 2) gibt 4.806 pro Gruppe. Der Zuwachs ist 0.01, ein Anteil, nicht 1. Ein größerer Zuwachs zeigt sich mit weniger Daten: 1 Punkt braucht etwa 2,8-mal weniger Besuche als 0,6 Punkte, denn (1 / 0,6)² ≈ 2,8.
Die Idee
Schau nicht vor dem Ende nach
Die Versuchung ist, jeden Tag auf das Ergebnis zu schauen. Hier ist p, berechnet aus allen Besuchen bis zu jedem Tag:
An Tag drei ist p = 0,053, an Tag vier 0,077, an Tag fünf 0,041. Hättest du an Tag fünf aufgehört, hättest du einen Sieg erklärt. Hier ist der neue Warenkorb wirklich besser, aber das zeigt sich aus dem ganzen Test. Die Regel „Ich höre auf, sobald p unter 0,05 fällt“ ist der Fehler selbst.
Warum? Prüf es mit einem A/A-Test: Beide Gruppen sehen dasselbe, und es gibt keinen Unterschied. Wir simulieren 1.000 solche Tests über 14 Tage und schauen jeden Tag auf p:
Schaust du nur am Ende, sind die falschen „Siege“ 4,9 %, so viel, wie die Schwelle von 0,05 verspricht. Schaust du jeden Tag und hörst beim ersten p unter 0,05 auf, sind es 21,7 %: viermal so viele. Das Rauschen hat 14 Chancen, unter die Linie zu tauchen.
Die Idee
Viele Kennzahlen, viele Segmente
Der neue Warenkorb bringt mehr Bestellungen. Sind sie auch größer? Vergleiche den Wert pro Bestellung:
26,30 € mit dem neuen Warenkorb und 26,71 € mit dem alten, p = 0,73. Es gibt keinen Beleg dafür, dass der Warenkorb den Bestellwert ändert. Das heißt nicht „wir haben bewiesen, dass sie gleich sind“: Es kann einen kleinen Unterschied geben, aber dieser Test sieht ihn nicht.
Stell dir jetzt einen Bericht mit 20 Kennzahlen vor: Bestellungen, Wert, Retouren, Zeit auf der Seite … Jede Kennzahl ohne echten Unterschied hat eine Chance von 5 %, mit p unter 0,05 herauszukommen. Wie oft „gewinnt“ mindestens eine?
Eine Kennzahl „gewinnt“ in 5,1 % der Fälle, wie erwartet. Aber mindestens eine von 20 „gewinnt“ in 64,1 % der Tests. Dasselbe gilt für Segmente: Handy, Desktop, Neukunden, jeder Wochentag. Darum wird die Hauptkennzahl vor dem Test gewählt. Ein zufälliger „Sieg“ bei der 20. Kennzahl ist eine Idee für den nächsten Test, keine Schlussfolgerung.
Die Idee
Warum der Test „verursacht“ sagt
Warum glaubst du, dass der Warenkorb mehr Bestellungen verursacht und nicht nur mit ihnen einhergeht? Weil die Variante zufällig zugewiesen wurde. Der Zufall gleicht alles aus, was du nicht misst. Hier sind die Geräte in beiden Gruppen:
In beiden Gruppen sind Desktops 35 % und Handys 65 %. Dasselbe gilt für die Uhrzeit, den Tag, die Gewohnheiten der Leute: Die Gruppen unterscheiden sich nur im Warenkorb. Der Abstand bei den Bestellungen kommt also von ihm.
Stammen die Daten nicht aus einem Test, ist das nicht so. In der nächsten Lektion scheint ein Banner die Bestellungen zu steigern, doch auf jedem Gerät für sich tut es das nicht.
Übung
Ein Bericht für den Chef
Der Chef fragt: „Bringt der neue Warenkorb mehr Geld pro Besuch?“ Speichere in per_visit den durchschnittlichen Umsatz pro Besuch für jede Variante (alle Besuche, auch die ohne Bestellung) und in p den p-Wert des Vergleichs mit scipy.stats.ttest_ind.
Lösung
import pandas as pd
visits = pd.read_csv('ab_visits.csv')
from scipy import stats
per_visit = visits.groupby('variant')['revenue'].mean()
new = visits.loc[visits['variant'] == 'new', 'revenue']
old = visits.loc[visits['variant'] == 'old', 'revenue']
p = stats.ttest_ind(new, old).pvalue
print(per_visit.round(2))
print(round(p, 3))visits.groupby('variant')['revenue'].mean() gibt 0,98 € pro Besuch mit dem neuen Warenkorb und 0,83 € mit dem alten, und ttest_ind gibt p ≈ 0,032. Die Besuche ohne Bestellung bringen 0 € und zählen im Mittelwert. Nimmst du nur die Bestellungen, bekommst du 26,30 € und 26,71 € und p = 0,73: eine andere Frage. Die Schlussfolgerung für den Bericht: Der neue Warenkorb bringt mehr Geld, weil er mehr Bestellungen bringt, nicht größere.
Hättest du es von Anfang an geplant: Wie viele Tage hätte der Test laufen sollen? Die Besuche pro Tag sind im Mittel len(visits) / 14. Speichere in per_group die Besuche pro Gruppe nach der Regel (ein Zuwachs von 0,6 Punkten bei 3,1 %), in per_day die Besuche pro Tag und in days die Tage, aufgerundet.
Lösung
import math
import pandas as pd
visits = pd.read_csv('ab_visits.csv')
base = 0.031
lift = 0.006
per_group = 16 * base * (1 - base) / lift ** 2
per_day = len(visits) / 14
days = math.ceil(2 * per_group / per_day)
print(round(per_day), days)Du brauchst etwa 13.351 Besuche pro Gruppe, und es gibt zwei Gruppen: insgesamt etwa 26.701. Pro Tag kommen etwa 2.013 Besuche, also sind die Tage math.ceil(26701 / 2013) = 14. Der Test war genau so lange geplant. Mit per_group / per_day bekämst du 7 Tage: genug für eine Gruppe.
Test
Teste dich
Verwandte Lektionen
Abschnitt „Verwandte Lektionen“- Baut auf: Das erste Diagramm · Stichprobe und Grundgesamtheit · Konfidenzintervalle · Eine Hypothese testen
- Geht weiter in: Korrelation und Ursache
- Aufgaben zum Thema: Statistik für Entscheidungen