Calculator de Semnificație A/B
Verifică dacă rezultatul testului A/B este semnificativ din punct de vedere statistic. Introduceți vizitatori și conversii pentru a obține p-value, scor z, interval de încredere și ridicare relativă.
Calculator de Semnificație A/B
Introduceți vizitatori și conversii pentru fiecare variantă pentru a verifica dacă diferența este reală sau doar zgomot.
Rezultate
Semnificativ din punct de vedere statistic
Diferența este puțin probabil să se datoreze hazardului la nivelul de încredere ales.
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.
Documentație
Testare A/B într-un minut
Ai schimbat un buton, un titlu sau un flux de finalizare. Versiunea A este cea veche, versiunea B este cea nouă. B arată mai bine — a convertit 15% din vizitatori versus 10% pentru A. Dar această diferență ar putea fi doar norocul, la fel cum aruncarea unei monede de zece ori poate da șapte capete?
Calculator-ul răspunde exact asta. Introduci câți oameni au văzut fiecare versiune și câți au convertit, și ți-o spune probabilitatea ca diferența pe care ai măsurat-o să fie reală mai degrabă decât zgomot aleator. Dacă acea probabilitate este suficient de mare, ai un câștigător. Dacă nu, continui să rulezi testul.
Singurul număr de urmărit este p-value: șansa de a vedea o diferență cel puțin atât de mare dacă cele două versiuni ar fi de fapt identice. O p-value mică (să zicem, sub 0.05) înseamnă "asta s-ar întâmpla rar din noroc, deci diferența este probabil reală."
Cum să-l folosești
- Vizitatori — câți oameni unici au fost arătați fiecare versiune.
- Conversii — câți din ei au făcut lucrul pe care ți-l dorești (au cumpărat, s-au înscris, au făcut clic).
- Nivel de încredere — cât de sigur dorești să fii înainte de a proclama un câștigător. 95% este standardul industriei.
- Ipoteză — bilateral întreabă "este B diferit de A?" (mai sigur, implicit); unilateral întreabă doar "este B mai bun decât A?" (mai sensibil, dar trebuie să decizi direcția înainte de a rula testul).
Rezultatul se actualizează în timp real și intrările sunt stocate în URL-ul paginii, deci poți adăuga în marcaje sau partaja un rezultat. Reset șterge formularul; Load sample data completează un exemplu lucrat.
Un exemplu lucrat
| Vizitatori | Conversii | Rată | |
|---|---|---|---|
| A (control) | 1,000 | 100 | 10.0% |
| B (variație) | 1,000 | 150 | 15.0% |
Aceasta este o ridicare absolută de 5 puncte procentuale și o ridicare +50% relativă. Calculator-ul returnează o p-value de aproximativ 0.0007 — sub 0.05 — deci cu 95% încredere rezultatul este semnificativ din punct de vedere statistic. Aproximativ, dacă cele două versiuni ar fi fost cu adevărat identice, ai vedea o diferență atât de mare mai puțin decât o dată la o mie de teste.
Matematica (testul z cu două proporții)
Sub capot, aceasta este testul standard z cu două proporții, același test predat în statistica introductivă și folosit de instrumentele A/B principale.
-
Rata de conversie a fiecărui grup:
unde sunt conversiile și sunt vizitatorii.
-
Rata agregată, presupunând (pentru ipoteza nulă) că ambele grupuri împărtășesc o rată adevărată:
-
Eroare standard a diferenței:
-
Scorul z — câte erori standard sunt distanțate cele două rate:
-
p-value vine din distribuția normală standard . Bilateral: . Unilateral: .
-
Semnificativ când , unde (deci 0.05 la 95%).
Calculator-ul raportează, de asemenea, un interval de încredere pentru diferență, calculat cu eroarea standard neagregată : gama plauzibilă pentru golul adevărat. Dacă acel interval exclude 0, rezultatul este semnificativ.
La 95% încredere, un z peste ±1.96 (cozile umbrite, 5% din suprafață) numără ca semnificativ.
Citind rezultatul cu sinceritate
- Semnificația statistică nu este semnificație comercială. O ridicare de 0.1% poate fi reală din punct de vedere statistic, dar nu merită publicată.
- Nu te uita și nu te opri devreme. Verificarea p-value în fiecare zi și oprirea în momentul în care scade sub 0.05 vânează rata fals-pozitivilor. Decide mărimea eșantionului înainte și lasă testul să se termine.
- Urmărește regula de mărime a eșantionului. Aproximarea normală este de încredere când fiecare grup are cel puțin ~10 conversii și ~10 non-conversii. Cu numere minuscule, trata rezultatul ca doar direcțional.
- Încredere ≠ probabilitate B este mai bun. Un nivel de încredere de 95% înseamnă că procedura este greșită cel mult 5% din timp pe termen lung — este o afirmație frecventistă, nu "95% șansă ca B să câștige."
- Un test, o metrică. Testarea mai multor metrici sau variante simultan multiplică șansa unei gafe; corectează-o (de ex. Bonferroni) sau pre-înregistrează metrica unică care decide testul.
Calculează-l singur
Fiecare snippet calculează p-value-ul bilateral pentru exemplul lucrat de mai sus.
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
Ce dimensiune a eșantionului am nevoie? Suficient încât o ridicare semnificativă ar fi detectabilă. Ca podea, urmăresc cel puțin câteva sute de conversii per variantă; utilizează un calculator dedicat de mărime a eșantionului cu rata de bază și cea mai mică ridicare care merită detectată.
Bilateral sau unilateral? Utilizează bilateral decât dacă ai un motiv ferm, pre-stabilit să numai ții cont de îmbunătățire. Unilateral dublează sensibilitatea dar interzice reacția la B fiind mai rău.
De ce arată calculator-ul un interval de încredere? Arată gama plauzibilă a diferenței adevărate, nu doar un verdict da/nu. Un interval larg care umblă în jurul 0 înseamnă "nu suficiente date deocamdată."
Este asta Bayesian? Nu — este un test z frecventist, cea mai larg predate și utilizată metodă. Instrumentele A/B Bayesiene raportează "probabilitate B bate A" în loc de o p-value; ambele sunt valide, răspund la întrebări ușor diferite.