Kalkulator Istotności Testu A/B
Sprawdź czy wynik twojego testu A/B jest istotny statystycznie. Wprowadź odwiedzających i konwersje aby uzyskać p-wartość, wynik z, przedział ufności i wzrost względny.
Kalkulator Istotności Testu A/B
Wprowadź odwiedzających i konwersje dla każdego wariantu aby sprawdzić czy różnica jest rzeczywista czy tylko szum.
Wyniki
Istotne statystycznie
Różnica jest mało prawdopodobna aby być spowodowana przypadkiem na twoim wybranym poziomie pewności.
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.
Dokumentacja
Testowanie A/B w ciągu minuty
Zmieniłeś przycisk, nagłówek lub przepływ checkout. Wersja A to stara, wersja B to nowa. B wygląda lepiej — przeliczył 15% odwiedzających w stosunku do 10% dla A. Ale czy ta różnica mogła być tylko szczęściem, tak jak rzucanie monetą dziesięć razy może dać siedem reszek?
Ten kalkulator odpowiada dokładnie na to pytanie. Wprowadzisz ile osób widziało każdą wersję i ile się przeliczył, a on ci powie prawdopodobieństwo, że zmierzona przez ciebie różnica jest rzeczywista, a nie szum losowy. Jeśli to prawdopodobieństwo jest wystarczająco wysokie, masz zwycięzcę. Jeśli nie, kontynuujesz test.
Jedna liczba, którą warto obserwować, to p-wartość: szansa na zobaczenie przerwy co najmniej tak dużej jeśli obie wersje były faktycznie identyczne. Mała p-wartość (powiedzmy, poniżej 0,05) oznacza „to byłoby rzadko zdarzać się przypadkowo, więc różnica jest prawdopodobnie rzeczywista".
Jak z niego korzystać
- Odwiedzający — ile unikalnych osób zobaczył każdą wersję.
- Konwersje — ile z nich zrobiło to, na czym ci zależy (kupiło, zarejestrowało się, kliknęło).
- Poziom pewności — jak bardzo chcesz być pewny przed ogłoszeniem zwycięzcy. 95% to standard branżowy.
- Hipoteza — dwustronnie pyta „czy B różni się od A?" (bezpieczniejsze, domyślne); jednostronnie pyta tylko „czy B jest lepsze od A?" (bardziej czułe, ale musisz zdecydować kierunek przed uruchomieniem testu).
Wynik aktualizuje się na żywo a dane wejściowe są przechowywane w adresie URL strony, możesz więc oznaczyć zakładką lub udostępnić wynik. Resetuj czyści formularz; Załaduj przykładowe dane wypełnia pracowany przykład.
Pracowany przykład
| Odwiedzający | Konwersje | Stopa | |
|---|---|---|---|
| A (kontrola) | 1 000 | 100 | 10,0% |
| B (wariacja) | 1 000 | 150 | 15,0% |
To wzrost absolutny o 5 punktów procentowych i wzrost względny +50%. Kalkulator zwraca p-wartość około 0,0007 — poniżej 0,05 — więc przy 95% pewności wynik jest istotny statystycznie. Najprościej mówiąc, gdyby obie wersje były naprawdę identyczne, taką dużą różnicę zobaczyłbyś rzadziej niż raz na tysiąc testów.
Matematyka (test z dla dwóch proporcji)
Pod spodem jest to standardowy test z dla dwóch proporcji, ten sam test nauczany w kursach statystyki wprowadzającej i używany przez główne narzędzia A/B.
-
Stopa konwersji każdej grupy:
gdzie to konwersje a to odwiedzający.
-
Stopa pooled, zakładając (dla hipotezy zerowej) obie grupy dzielą jedną prawdziwą stopę:
-
Błąd standardowy różnicy:
-
Wynik z — jak wiele błędów standardowych jest osobno dwie stopy:
-
p-wartość pochodzi ze standardowego rozkładu normalnego . Dwustronna: . Jednostronna: .
-
Istotna gdy , gdzie (więc 0,05 przy 95%).
Kalkulator również raportuje przedział ufności dla różnicy, wyliczony z niepooled błędem standardowym : wiarygodny zakres dla prawdziwej luki. Jeśli ten przedział wyklucza 0, wynik jest istotny.
Przy 95% pewności, z poza ±1,96 (zaciemnione ogony, 5% obszaru) liczy się jako istotny.
Czytanie wyniku szczerze
- Istotność statystyczna to nie istotność biznesowa. Wzrost 0,1% może być statystycznie rzeczywisty a jednak nie wart wysłania.
- Nie podglądaj i nie zatrzymuj się wcześnie. Codzienne sprawdzanie p-wartości i zatrzymanie się w momencie, gdy spadnie poniżej 0,05, zwiększa poziom fałszywych alarmów. Zdecyduj wielkość próby z góry i pozwól testowi się skończyć.
- Obserwuj regułę kciuka wielkości próby. Przybliżenie normalne jest wiarygodne gdy każda grupa ma co najmniej ~10 konwersji i ~10 niekonwersji. Z maleńkimi liczbami traktuj wynik jako kierunkowy tylko.
- Pewność ≠ prawdopodobieństwo że B jest lepsze. Poziom pewności 95% oznacza, że procedura jest błędna co najwyżej 5% czasu w długim okresie — to stwierdzenie częstościowe, nie „95% szansy że B wygra".
- Jeden test, jedna metrika. Testowanie wielu metryk lub wariantów na raz zwielokrotnia szansę przypadkowego zbiegu; skoryguj to (np. Bonferroni) lub wstępnie zarejestruj pojedynczą metrikę, która decyduje test.
Oblicz to sam
Każdy fragment oblicza dwustronną p-wartość dla pracowanego przykładu powyżej.
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
Jaka wielkość próby mi potrzebna? Wystarczająco dużo, aby znaczący wzrost byłby do wykrycia. Jako minimum postaraj się mieć co najmniej kilkaset konwersji na wariant; użyj dedykowanego kalkulatora wielkości próby z twoją bazową stopą i najmniejszym wzrostem wartym wykrycia.
Dwustronnie czy jednostronnie? Użyj dwustronnie chyba że masz zdecydowany, wcześniej zaangażowany powód by dbać tylko o ulepszenie. Jednostronnie podwaja twoją czułość ale zabrania reagowania na B będące gorsze.
Dlaczego kalkulator pokazuje przedział ufności? Pokazuje wiarygodny zakres prawdziwej różnicy, nie tylko tak/nie werdykt. Szeroki przedział, który przechodzi przez 0 oznacza „nie wystarczy jeszcze danych".
Czy to Bayesian? Nie — to test z częstościowy, najszerzej nauczana i używana metoda. Narzędzia A/B Bayesian raportują „prawdopodobieństwo że B bije A" zamiast p-wartości; oba są ważne, odpowiadają trochę na inne pytania.