Calculadora de Significância de Testes A/B
Verifique se o resultado do seu teste A/B é estatisticamente significativo. Insira visitantes e conversões para obter o p-valor, pontuação Z, intervalo de confiança e aumento relativo.
Calculadora de Significância de Testes A/B
Insira visitantes e conversões para cada variante para verificar se a diferença é real ou apenas ruído.
Resultados
Estatisticamente Significativo
A diferença é improvável ser devido ao acaso no seu nível de confiança escolhido.
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ção
Testes A/B em um minuto
Você mudou um botão, um título ou um fluxo de checkout. A versão A é a antiga, a versão B é a nova. B parece melhor — converteu 15% dos visitantes em comparação com 10% para A. Mas essa diferença poderia ser apenas sorte, da mesma forma que jogar uma moeda dez vezes pode dar sete caras?
Esta calculadora responde exatamente isso. Você informa quantas pessoas viram cada versão e quantas se converteram, e ela diz a probabilidade de que a diferença medida seja real em vez de ruído aleatório. Se essa probabilidade for alta o suficiente, você tem um vencedor. Caso contrário, você continua executando o teste.
O número a observar é o p-valor: a chance de ver uma diferença pelo menos tão grande se as duas versões fossem realmente idênticas. Um p-valor pequeno (digamos, abaixo de 0,05) significa "isso raramente aconteceria por sorte, então a diferença é provavelmente real."
Como usar
- Visitantes — quantas pessoas únicas viram cada versão.
- Conversões — quantas delas fizeram o que você se importa (compraram, se cadastraram, clicaram).
- Nível de confiança — o quanto você quer estar certo antes de declarar um vencedor. 95% é o padrão da indústria.
- Hipótese — bilateral pergunta "B é diferente de A?" (mais seguro, o padrão); unilateral pergunta apenas "B é melhor que A?" (mais sensível, mas você deve decidir a direção antes de executar o teste).
O resultado é atualizado em tempo real e as entradas são armazenadas na URL da página, para que você possa marcador ou compartilhar um resultado. Redefinir limpa o formulário; Carregar dados de exemplo preenche com um exemplo resolvido.
Um exemplo resolvido
| Visitantes | Conversões | Taxa | |
|---|---|---|---|
| A (controle) | 1.000 | 100 | 10,0% |
| B (variação) | 1.000 | 150 | 15,0% |
Isso representa um aumento absoluto de 5 pontos percentuais e um aumento relativo de +50%. A calculadora retorna um p-valor de cerca de 0,0007 — abaixo de 0,05 — então com 95% de confiança o resultado é estatisticamente significativo. Aproximadamente, se as duas versões fossem realmente idênticas, você veria uma diferença tão grande menos de uma vez em mil testes.
A matemática (teste z de duas proporções)
Por baixo dos panos, este é o teste z de duas proporções padrão, o mesmo teste ensinado em estatística introdutória e usado por ferramentas A/B convencionais.
-
Taxa de conversão de cada grupo:
onde é conversões e é visitantes.
-
Taxa agrupada, assumindo (para a hipótese nula) que ambos os grupos compartilham uma taxa verdadeira:
-
Erro padrão da diferença:
-
O z-score — quantos erros padrão as duas taxas estão separadas:
-
O p-valor vem da distribuição normal padrão . Bilateral: . Unilateral: .
-
Significativo quando , onde (então 0,05 em 95%).
A calculadora também relata um intervalo de confiança para a diferença, calculado com o erro padrão não agrupado : o intervalo plausível para a diferença verdadeira. Se esse intervalo exclui 0, o resultado é significativo.
Com 95% de confiança, um z além de ±1,96 (as caudas sombreadas, 5% da área) conta como significativo.
Lendo o resultado honestamente
- Significância estatística não é significância comercial. Um aumento de 0,1% pode ser estatisticamente real, mas não vale a pena entregar.
- Não espreite e pare cedo. Verificar o p-valor todos os dias e parar no momento em que cai abaixo de 0,05 inflaciona sua taxa de falsos positivos. Decida o tamanho da amostra antecipadamente e deixe o teste terminar.
- Observe a regra prática do tamanho da amostra. A aproximação normal é confiável quando cada grupo tem pelo menos ~10 conversões e ~10 não-conversões. Com números pequenos, trate o resultado apenas como direcional.
- Confiança ≠ probabilidade de B ser melhor. Um nível de confiança de 95% significa que o procedimento está errado no máximo 5% do tempo no longo prazo — é uma declaração frequentista, não "95% de chance de B vencer."
- Um teste, uma métrica. Testar muitas métricas ou variantes ao mesmo tempo multiplica a chance de uma falha; corrija isso (por exemplo, Bonferroni) ou pré-registre a única métrica que decide o teste.
Calcule você mesmo
Cada trecho calcula o p-valor bilateral para o exemplo acima.
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 = visitantes do controle, conversões ; A2,B2 = visitantes da variação, conversões
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
3PERGUNTAS FREQUENTES
Qual tamanho de amostra preciso? O suficiente para que um aumento significativo seja detectável. Como mínimo, tenha como objetivo pelo menos algumas centenas de conversões por variante; use uma calculadora de tamanho de amostra dedicada com sua taxa de linha de base e o menor aumento que vale a pena detectar.
Bilateral ou unilateral? Use bilateral a menos que você tenha uma razão firme e pré-comprometida para se importar apenas com a melhoria. Unilateral dobra sua sensibilidade, mas proíbe reagir a B ser pior.
Por que a calculadora mostra um intervalo de confiança? Ela mostra o intervalo plausível da diferença verdadeira, não apenas um veredito sim/não. Um intervalo amplo que atravessa 0 significa "dados insuficientes ainda."
Isso é bayesiano? Não — é um teste z frequentista, o método mais amplamente ensinado e usado. As ferramentas bayesianas de A/B relatam "probabilidade de B vencer A" em vez de um p-valor; ambas são válidas, elas respondem perguntas ligeiramente diferentes.