A/B-Test-Signifikanzrechner
Überprüfen Sie, ob Ihr A/B-Test-Ergebnis statistisch signifikant ist. Geben Sie Besucher und Konversionen ein, um den p-Wert, z-Wert, Konfidenzintervall und relativen Anstieg zu erhalten.
A/B-Test-Signifikanzrechner
Geben Sie Besucher und Konversionen für jede Variante ein, um zu überprüfen, ob der Unterschied real ist oder nur Rauschen.
Ergebnisse
Statistisch Signifikant
Der Unterschied ist bei Ihrem gewählten Konfidenzniveau unwahrscheinlich zufällig.
Chance this gap is just luck — lower is stronger.
How far apart the two rates are, in standard errors.
The likely range for the true difference.
Dokumentation
A/B-Tests in einer Minute
Du hast einen Button, eine Überschrift oder einen Checkout-Ablauf geändert. Version A ist die alte, Version B die neue. B sieht besser aus – sie konvertierte 15% der Besucher gegenüber 10% für A. Aber könnte diese Lücke nur Glück sein, wie wenn man zehnmal eine Münze werfen kann und sieben Kopf erhält?
Dieser Rechner beantwortet genau das. Du gibst ein, wie viele Menschen jede Version sahen und wie viele konvertierten, und er sagt dir die Wahrscheinlichkeit, dass der Unterschied, den du gemessen hast, real und nicht zufälliges Rauschen ist. Wenn diese Wahrscheinlichkeit hoch genug ist, hast du einen Gewinner. Wenn nicht, führst du den Test weiter.
Die eine Zahl, auf die du achten musst, ist der p-Wert: die Chance, eine Lücke so groß oder größer zu sehen, wenn die beiden Versionen tatsächlich identisch wären. Ein kleiner p-Wert (sagen wir unter 0,05) bedeutet „dies würde selten per Zufall passieren, also ist der Unterschied wahrscheinlich real".
Wie man es benutzt
- Besucher – wie viele einzigartige Menschen wurden jede Version gezeigt.
- Konversionen – wie viele von ihnen machten das, was dir wichtig ist (kaufen, sich anmelden, klicken).
- Konfidenzniveau – wie sicher du sein willst, bevor du einen Gewinner ausrufst. 95% ist der Industrie-Standard.
- Hypothese – zwei-seitig fragt „ist B anders als A?" (sicherer, die Voreinstellung); ein-seitig fragt nur „ist B besser als A?" (empfindlicher, aber du musst die Richtung vor dem Ausführen des Tests entscheiden).
Das Ergebnis wird live aktualisiert und die Eingaben werden in der Seiten-URL gespeichert, sodass du ein Ergebnis mit Lesezeichen versehen oder teilen kannst. Zurücksetzen löscht das Formular; Beispieldaten laden füllt ein durchgearbeitetes Beispiel aus.
Ein durchgearbeitetes Beispiel
| Besucher | Konversionen | Rate | |
|---|---|---|---|
| A (Kontrolle) | 1.000 | 100 | 10,0% |
| B (Variation) | 1.000 | 150 | 15,0% |
Das ist ein Anstieg um 5 Prozentpunkte absolut und ein +50%-Anstieg relativ. Der Rechner gibt einen p-Wert von etwa 0,0007 zurück – unter 0,05 – sodass das Ergebnis bei 95%-Konfidenz statistisch signifikant ist. Grob gesagt: Wenn die beiden Versionen wirklich identisch wären, würdest du einen Unterschied dieser Größe in weniger als einem von tausend Tests sehen.
Die Mathematik (Zwei-Proportionen-z-Test)
Unter der Haube ist dies der Standard-Zwei-Proportionen-z-Test, der gleiche Test, der in der Einführungsstatistik gelehrt wird und von den Mainstream-A/B-Tools verwendet wird.
-
Konversionsrate jeder Gruppe:
wobei Konversionen und Besucher sind.
-
Gepoolte Rate, unter der Annahme (für die Nullhypothese), dass beide Gruppen eine gemeinsame wahre Rate haben:
-
Standardfehler der Differenz:
-
Der z-Wert – wie viele Standardfehler die beiden Raten auseinander liegen:
-
Der p-Wert ergibt sich aus der Standardnormalverteilung . Zwei-seitig: . Ein-seitig: .
-
Signifikant, wenn , wobei (also 0,05 bei 95%).
Der Rechner meldet auch ein Konfidenzintervall für die Differenz, berechnet mit dem ungepoolten Standardfehler : der plausible Bereich für die wahre Lücke. Wenn dieses Intervall 0 ausschließt, ist das Ergebnis signifikant.
Bei 95%-Konfidenz zählt ein z über ±1,96 (die schattierten Schwänze, 5% der Fläche) als signifikant.
Das Ergebnis ehrlich lesen
- Statistische Signifikanz ist nicht geschäftliche Signifikanz. Ein Anstieg von 0,1% kann statistisch real sein, lohnt sich aber möglicherweise nicht zu versenden.
- Schau nicht früh rein und stoppe nicht früh. Das Überprüfen des p-Werts jeden Tag und das Stoppen in dem Moment, in dem er unter 0,05 sinkt, inflationiert deine falsch-positiven Rate. Entscheide die Stichprobengröße im Voraus und lass den Test zu Ende laufen.
- Achte auf die Faustregel für die Stichprobengröße. Die Normalannäherung ist zuverlässig, wenn jede Gruppe mindestens ~10 Konversionen und ~10 Nicht-Konversionen hat. Mit winzigen Zahlen, behandle das Ergebnis nur als richtungsweisend.
- Konfidenz ≠ Wahrscheinlichkeit, dass B besser ist. Ein 95%-Konfidenzniveau bedeutet, dass das Verfahren im Laufe der Zeit in höchstens 5% der Fälle falsch ist – es ist eine frequistische Aussage, nicht „95% Chance B gewinnt".
- Ein Test, eine Metrik. Das Testen mehrerer Metriken oder Varianten gleichzeitig multipliziert die Chance auf einen Zufall; korrigiere dafür (z.B. Bonferroni) oder melde die einzelne Metrik vor, die den Test entscheidet.
Berechne es selbst
Jedes Snippet berechnet den zweiseitigen p-Wert für das oben durchgearbeitete Beispiel.
1=2*(1-NORM.S.DIST(
2 (B2/A2 - B1/A1) /
3 SQRT(((B1+B2)/(A1+A2))*(1-(B1+B2)/(A1+A2))*(1/A1+1/A2)),
4 TRUE))
5' A1,B1 = control visitors, conversions ; A2,B2 = variation visitors, conversions
61from math import sqrt, erf
2
3def ab_pvalue(n1, x1, n2, x2, two_sided=True):
4 p1, p2 = x1 / n1, x2 / n2
5 p = (x1 + x2) / (n1 + n2)
6 se = sqrt(p * (1 - p) * (1 / n1 + 1 / n2))
7 z = (p2 - p1) / se
8 phi = lambda v: 0.5 * (1 + erf(v / sqrt(2))) # standard normal CDF
9 return 2 * (1 - phi(abs(z))) if two_sided else 1 - phi(z)
10
11print(ab_pvalue(1000, 100, 1000, 150)) # ~0.00072
121// erf via Abramowitz & Stegun 7.1.26
2function erf(x) {
3 const s = x < 0 ? -1 : 1;
4 x = Math.abs(x);
5 const t = 1 / (1 + 0.3275911 * x);
6 const y = 1 - ((((1.061405429 * t - 1.453152027) * t + 1.421413741) * t
7 - 0.284496736) * t + 0.254829592) * t * Math.exp(-x * x);
8 return s * y;
9}
10const phi = z => 0.5 * (1 + erf(z / Math.SQRT2));
11
12function abPValue(n1, x1, n2, x2, twoSided = true) {
13 const p1 = x1 / n1, p2 = x2 / n2, p = (x1 + x2) / (n1 + n2);
14 const se = Math.sqrt(p * (1 - p) * (1 / n1 + 1 / n2));
15 const z = (p2 - p1) / se;
16 return twoSided ? 2 * (1 - phi(Math.abs(z))) : 1 - phi(z);
17}
18console.log(abPValue(1000, 100, 1000, 150)); // ~0.00072
191public static double abPValue(int n1, int x1, int n2, int x2) {
2 double p1 = (double) x1 / n1, p2 = (double) x2 / n2;
3 double p = (double) (x1 + x2) / (n1 + n2);
4 double se = Math.sqrt(p * (1 - p) * (1.0 / n1 + 1.0 / n2));
5 double z = (p2 - p1) / se;
6 // Phi via the error function; erf approximated (A&S 7.1.26) separately.
7 double phi = 0.5 * (1 + erf(Math.abs(z) / Math.sqrt(2)));
8 return 2 * (1 - phi);
9}
101static double AbPValue(int n1, int x1, int n2, int x2) {
2 double p1 = (double)x1 / n1, p2 = (double)x2 / n2;
3 double p = (double)(x1 + x2) / (n1 + n2);
4 double se = Math.Sqrt(p * (1 - p) * (1.0 / n1 + 1.0 / n2));
5 double z = (p2 - p1) / se;
6 double phi = 0.5 * (1 + Erf(Math.Abs(z) / Math.Sqrt(2)));
7 return 2 * (1 - phi);
8}
91#include <cmath>
2
3double ab_pvalue(int n1, int x1, int n2, int x2) {
4 double p1 = (double)x1 / n1, p2 = (double)x2 / n2;
5 double p = (double)(x1 + x2) / (n1 + n2);
6 double se = std::sqrt(p * (1 - p) * (1.0 / n1 + 1.0 / n2));
7 double z = (p2 - p1) / se;
8 double phi = 0.5 * (1 + std::erf(std::fabs(z) / std::sqrt(2.0)));
9 return 2 * (1 - phi);
10}
111import "math"
2
3func abPValue(n1, x1, n2, x2 float64) float64 {
4 p1, p2 := x1/n1, x2/n2
5 p := (x1 + x2) / (n1 + n2)
6 se := math.Sqrt(p * (1 - p) * (1/n1 + 1/n2))
7 z := (p2 - p1) / se
8 phi := 0.5 * (1 + math.Erf(math.Abs(z)/math.Sqrt2))
9 return 2 * (1 - phi)
10}
111// erf from the `libm` crate; std has no erf.
2fn ab_pvalue(n1: f64, x1: f64, n2: f64, x2: f64) -> f64 {
3 let (p1, p2) = (x1 / n1, x2 / n2);
4 let p = (x1 + x2) / (n1 + n2);
5 let se = (p * (1.0 - p) * (1.0 / n1 + 1.0 / n2)).sqrt();
6 let z = (p2 - p1) / se;
7 let phi = 0.5 * (1.0 + libm::erf(z.abs() / 2f64.sqrt()));
8 2.0 * (1.0 - phi)
9}
101function ab_pvalue($n1, $x1, $n2, $x2) {
2 $p1 = $x1 / $n1; $p2 = $x2 / $n2;
3 $p = ($x1 + $x2) / ($n1 + $n2);
4 $se = sqrt($p * (1 - $p) * (1 / $n1 + 1 / $n2));
5 $z = ($p2 - $p1) / $se;
6 $phi = 0.5 * (1 + erf(abs($z) / sqrt(2)));
7 return 2 * (1 - $phi);
8}
91def ab_pvalue(n1, x1, n2, x2)
2 p1, p2 = x1.to_f / n1, x2.to_f / n2
3 p = (x1 + x2).to_f / (n1 + n2)
4 se = Math.sqrt(p * (1 - p) * (1.0 / n1 + 1.0 / n2))
5 z = (p2 - p1) / se
6 phi = 0.5 * (1 + Math.erf(z.abs / Math.sqrt(2)))
7 2 * (1 - phi)
8end
91# R has this built in: prop.test does the whole thing.
2prop.test(c(100, 150), c(1000, 1000), correct = FALSE)$p.value # ~0.00072
3FAQ
Welche Stichprobengröße brauchst du? Genug, damit ein aussagekräftiger Anstieg erkannt würde. Zielen Sie mindestens auf ein paar hundert Konversionen pro Variante ab; verwenden Sie einen dedizierten Stichprobengrößen-Rechner mit Ihrer Basisrate und dem kleinsten erkennbaren Anstieg.
Zwei-seitig oder ein-seitig? Verwende zwei-seitig, es sei denn, du hast einen festen, vor Commit eingegangenen Grund, nur um Verbesserungen zu kümmern. Ein-seitig verdoppelt deine Empfindlichkeit, verbietet aber, auf B zu reagieren, das schlechter ist.
Warum zeigt der Rechner ein Konfidenzintervall? Es zeigt den plausiblen Bereich der wahren Differenz, nicht nur ein Ja/Nein-Verdikt. Ein breites Intervall, das 0 überlagert, bedeutet „nicht genug Daten noch".
Ist dies Bayesianisch? Nein – es ist ein frequistischer z-Test, die am weitesten verbreitete und verwendete Methode. Bayesianische A/B-Tools berichten „Wahrscheinlichkeit B schlägt A" anstelle eines p-Werts; beides ist gültig, sie beantworten etwas andere Fragen.