Teste de Permutação em Teste A/B: p-valor sem fórmula
O teste de permutação embaralha os rótulos e monta a distribuição nula com os seus próprios dados. Quando ele salva um teste A/B e quando não muda nada.

📚 Este artigo faz parte do guia Significância Estatística em Teste A/B: O Guia.
O teste de permutação calcula o valor-p embaralhando os rótulos de controle e variação milhares de vezes em cima dos seus próprios dados, em vez de assumir que a diferença entre médias segue uma normal. Ele não é mais preciso sempre: numa divisão 50/50 com métrica bem comportada, ele devolve praticamente o mesmo número do teste z. Ele salva o resultado exatamente onde a aproximação normal quebra, e a simulação deste artigo mostra o tamanho do estrago: numa rampa de 1 por cento com receita por usuário, o teste z rejeitou 16,44 por cento dos testes A/A a um alfa nominal de 5 por cento, enquanto o teste de permutação ficou em 4,78 por cento. Este guia mostra como a conta funciona, onde ela importa, como rodar e o que ela não conserta. Faz parte do nosso guia completo de teste A/B e completa o que já dissemos sobre significância estatística.
A ideia do teste de permutação, em uma frase
Você tem 800 visitantes no controle com 24 conversões e 800 na variação com 36. A pergunta do teste é: se o rótulo “controle” ou “variação” não fizesse diferença nenhuma, com que frequência um sorteio aleatório desses 1.600 visitantes em dois grupos de 800 produziria uma diferença tão grande quanto a que você viu?
O teste z responde isso com uma fórmula que aproxima essa distribuição por uma normal. O teste de permutação responde a mesma pergunta literalmente: ele faz o sorteio, muitas vezes, e conta.
A justificativa formal é a mesma que sustenta o experimento. Guo, Lee e Toulis registram que a abordagem remonta a Fisher, em 1935, e que procedimentos desse tipo são válidos em amostra finita para distribuições de dados arbitrárias, porque exploram a variação conhecida na atribuição dos tratamentos, e não uma suposição sobre a população. Quem sorteou o tráfego foi você; o teste apenas repete esse sorteio.
Onde a fórmula fechada quebra
A resposta honesta é: menos vezes do que o folclore sugere. Um teste A/B típico, com divisão 50/50 e centenas de milhares de usuários, não precisa de permutação. Nós medimos isso.
O experimento simulado: receita por usuário, 4 por cento dos usuários compram, a compra segue uma lognormal, e o total de 20.000 usuários é dividido em proporções diferentes entre controle e variação. A métrica é violentamente assimétrica (o coeficiente de assimetria da amostra combinada fica em torno de 15, e a regra de bolso de Kohavi e coautores pediria cerca de 81.000 observações por braço só para a média ser aproximadamente normal). Rodamos milhares de testes A/A, ou seja, testes em que os dois braços vêm exatamente da mesma distribuição e qualquer resultado significante é falso positivo.
| divisão controle/variação | usuários no controle | usuários na variação | teste z: cauda “variação pior” | teste z: cauda “variação melhor” | teste z: total | permutação: total | réplicas |
|---|---|---|---|---|---|---|---|
| 50/50 | 10.000 | 10.000 | 2,40% | 2,45% | 4,85% | 5,00% | 4.000 |
| 80/20 | 16.000 | 4.000 | 3,45% | 1,27% | 4,72% | 4,13% | 4.000 |
| 90/10 | 18.000 | 2.000 | 5,43% | 0,75% | 6,18% | 5,12% | 6.000 |
| 99/1 | 19.800 | 200 | 16,35% | 0,09% | 16,44% | 4,78% | 8.000 |
O nominal é 5 por cento no total e 2,5 por cento em cada cauda. Leia a tabela de cima para baixo:
Na divisão 50/50, o teste z está certo. 4,85 por cento contra um alvo de 5 por cento, com as duas caudas equilibradas, mesmo com assimetria de 15 e uma amostra sete vezes menor do que a regra de bolso pediria. Isso não é sorte: Kohavi e coautores fazem exatamente essa ressalva no artigo em que publicam a regra. Com divisão de tamanhos iguais, a distribuição da diferença fica aproximadamente simétrica, e é perfeitamente simétrica com assimetria zero sob a hipótese nula, então a regra deixa de dar um limite inferior útil. A assimetria da métrica se cancela entre os dois braços.
Conforme a divisão desequilibra, as caudas se desequilibram junto. Em 90/10 o total ainda parece quase aceitável (6,18 por cento), mas ele esconde uma cauda de 5,43 por cento contra 0,75 por cento. Ou seja: o teste erra quase sempre para o mesmo lado, declarando que o braço pequeno está pior.
Em 99/1 o resultado é indefensável. Um em cada seis testes A/A produz um resultado significante, e 16,35 dos 16,44 pontos vêm da cauda “o braço de 1 por cento está pior”. O teste de permutação, nos mesmos dados, ficou em 4,78 por cento, dentro do erro Monte Carlo da simulação (com 8.000 réplicas, o erro-padrão em torno de 5 por cento é 0,24 ponto percentual).
A conclusão prática é específica e não é “abandone o teste z”. É: em rampa de exposição, que é justamente quando você roda 1 por cento ou 5 por cento do tráfego numa variação nova, a leitura por aproximação normal de uma métrica de receita é o pior cenário possível, e ela erra sistematicamente contra a variação. É o mesmo cuidado que já pedimos ao falar de SRM e divisão desigual de tráfego, só que aqui o problema não é o sorteio, é a leitura.
O exemplo trabalhado: um teste de baixo tráfego
O segundo lugar onde a fórmula fechada erra é o mais comum de todos: contagens pequenas. Considere um teste de baixo volume, 800 visitantes por variação, 24 conversões no controle (3,000 por cento) e 36 na variação (4,500 por cento), um ganho relativo aparente de 50 por cento.
Teste z bilateral de duas proporções. "Sem significância" quase sempre quer dizer que falta amostra, não que as versões são iguais.
Colando esses números na calculadora acima, o teste z devolve z de 1,5791, valor-p de 0,11432 e intervalo de 95 por cento da diferença de menos 0,3604 a mais 3,3604 pontos percentuais. Sem significância.
Rodando o teste de permutação nos mesmos dados, com 100.000 embaralhamentos, 14.667 deles produziram uma diferença absoluta tão grande quanto a observada. O valor-p sai em 0,14668.
Aqui a conta tem uma checagem forte disponível: no caso binário com as marginais fixas, o teste de permutação converge para o teste exato de Fisher, que é calculável analiticamente pela distribuição hipergeométrica. O valor exato é 0,147193. A nossa aproximação Monte Carlo ficou a 0,00051 dele, e o erro-padrão Monte Carlo esperado com 100.000 embaralhamentos é 0,00112. A permutação acertou o alvo dentro de meio erro-padrão.
| método | valor-p | como foi obtido |
|---|---|---|
| teste z (aproximação normal) | 0,11432 | fórmula fechada, a mesma da calculadora acima |
| qui-quadrado com correção de Yates | 0,14776 | fórmula fechada com correção de continuidade |
| permutação Monte Carlo, 100.000 sorteios | 0,14668 | embaralhamento dos rótulos |
| teste exato de Fisher | 0,14719 | hipergeométrica, sem simulação |
A leitura: a aproximação normal devolve um valor-p 22 por cento menor do que o exato, e é sempre nessa direção com contagens desse tamanho. Num teste que já não é significante, isso é irrelevante. Num teste que ficou em 0,048 pela fórmula e 0,061 pelo exato, isso é a diferença entre publicar uma variação e não publicar. Repare também que a correção de Yates, que é fórmula fechada e roda em uma linha, chegou a 0,14776, praticamente no exato: em tabela 2 por 2 ela é um substituto barato e muito bom para a permutação. Isso é especialmente relevante para quem faz CRO em site de baixo tráfego, onde dezenas de conversões é o cenário normal e não a exceção.
Como rodar, em 15 linhas
O algoritmo cabe numa função. Este é o código que gerou os números acima, e ele não depende de biblioteca nenhuma:
function permutationP(controle, variacao, B, rand) {
const balde = controle.concat(variacao);
const n = balde.length, nA = controle.length;
const media = (a) => a.reduce((s, x) => s + x, 0) / a.length;
const observado = Math.abs(media(variacao) - media(controle));
let extremos = 0;
for (let k = 0; k < B; k++) {
for (let i = n - 1; i > 0; i--) { // embaralha o balde
const j = Math.floor(rand() * (i + 1));
[balde[i], balde[j]] = [balde[j], balde[i]];
}
let somaA = 0; for (let i = 0; i < nA; i++) somaA += balde[i];
let somaB = 0; for (let i = nA; i < n; i++) somaB += balde[i];
const dif = Math.abs(somaB / (n - nA) - somaA / nA);
if (dif >= observado - 1e-12) extremos++;
}
return (extremos + 1) / (B + 1); // Phipson e Smyth, 2010
}
Três detalhes que separam a implementação certa da errada:
O mais 1 no numerador e no denominador não é uma manha, é a conta correta. Phipson e Smyth mostraram que a versão ingênua, dividir a contagem por B, subestima o valor-p em cerca de 1 sobre B e aumenta a taxa de erro tipo I do teste. O argumento dos autores é que a permutação não estima a probabilidade de cauda de uma distribuição contínua: ela gera uma distribuição nula discreta exata, e a estatística observada é ela mesma um dos resultados possíveis. Somar 1 aos dois lados também elimina o absurdo de reportar valor-p exatamente zero.
A estatística tem que ser recalculada em cada sorteio, inclusive o denominador. Se você fixar a variância estimada nos dados originais e só embaralhar as médias, perde a propriedade que faz o método funcionar.
Use maior ou igual, não maior. A comparação com a estatística observada precisa incluir os empates, senão o teste fica anticonservador em métricas discretas.
Quantos embaralhamentos
A permutação Monte Carlo tem um erro próprio, e ele é fácil de dimensionar: o número de sorteios extremos é uma binomial, então o erro-padrão de um valor-p estimado em p é a raiz de p vezes (1 menos p) sobre B.
| embaralhamentos (B) | erro-padrão em p perto de 0,05 | meia largura do IC 95% | menor valor-p possível |
|---|---|---|---|
| 999 | 0,00690 | 0,01351 | 0,001000 |
| 9.999 | 0,00218 | 0,00427 | 0,000100 |
| 99.999 | 0,00069 | 0,00135 | 0,000010 |
| 999.999 | 0,00022 | 0,00043 | 0,000001 |
Com mil embaralhamentos, um valor-p estimado em 0,05 vem com um intervalo que vai de 0,036 a 0,064: você não sabe de que lado do limiar está. Dez mil já resolvem a decisão binária de significância. Cem mil valem quando você vai publicar o número, e só fazem diferença real quando o valor-p é pequeno. E note a última coluna: o menor valor-p que você consegue reportar é 1 sobre (B mais 1), então “p menor que 0,001” exige no mínimo 999 embaralhamentos, por definição, independentemente do quanto os dados são convincentes.
O que a permutação não conserta
Esta é a parte que os textos entusiasmados costumam pular. O teste de permutação corrige uma coisa: a aproximação da distribuição nula. Ele não corrige nada do que vem antes dela.
Em concreto:
- Ele exige permutabilidade sob a nula. Se o sorteio quebrou, e você tem divisão desigual de tráfego (SRM), as observações não são intercambiáveis entre os rótulos e o teste devolve um valor-p corretamente calculado sobre um experimento errado.
- Ele não protege contra dependência. Se a unidade de análise for o pageview mas o sorteio for por usuário, embaralhar pageviews individualmente destrói a estrutura de dependência e produz um valor-p otimista, exatamente do jeito que a fórmula i.i.d. produziria. O embaralhamento tem que acontecer na mesma unidade em que o sorteio aconteceu, tema que tratamos em unidade de sorteio.
- Ele não entrega intervalo de confiança. A permutação responde uma pergunta de teste. Para a incerteza em torno do efeito, o instrumento é o bootstrap, que reamostra com reposição dentro de cada grupo em vez de embaralhar entre grupos.
- Ele não conserta espiada. Rodar permutação a cada hora e parar quando der abaixo de 0,05 infla o erro tipo I do mesmo jeito que rodar teste z a cada hora, pelo motivo que descrevemos no problema da espiada.
- Ele não conserta assimetria em si. A regra de bolso de Kohavi, Deng, Longbotham e Xu diz que o mínimo de observações independentes para a média ser aproximadamente normal é 355 vezes o quadrado do coeficiente de assimetria, e vale a pena aplicá-la quando o módulo da assimetria passa de 1. Nas métricas do Bing que os autores publicam, receita por usuário tem assimetria de 17,9 e pede 114 mil observações; receita por usuário com teto tem 5,2 e pede 9,7 mil; sessões por usuário tem 3,6 e pede 4,70 mil. A permutação não reduz esse número, ela apenas deixa de precisar dele para calcular o valor-p. A conta de tamanho de amostra continua igual, e aplicar um teto na métrica continua sendo a intervenção que mais aumenta a sensibilidade.
Checklist de aplicação
- Divisão 50/50 e métrica binária com centenas de conversões por braço: use a fórmula. A permutação não vai mudar a terceira casa decimal.
- Menos de umas 100 conversões por braço: confira o valor-p com Fisher exato ou qui-quadrado com Yates antes de decidir. São fórmulas fechadas e a diferença já é material.
- Métrica contínua ou de contagem com divisão desigual (rampa de 1, 5 ou 10 por cento): permutação, sem discussão. É onde o teste z erra mais, e erra sempre contra o braço pequeno.
- Estatística sem fórmula fechada (diferença de medianas, diferença de quantis, razão de razões): permutação para o valor-p, bootstrap para o intervalo.
- Embaralhe na unidade do sorteio. Se sorteou usuário, permute usuários inteiros, com todos os eventos deles juntos.
- Fixe a semente do gerador e publique B. Um valor-p Monte Carlo sem o número de embaralhamentos é um número sem precisão declarada.
- Use (b mais 1) sobre (B mais 1). Sempre.
Faça isso automático na Donnu
O motivo pelo qual quase ninguém roda teste de permutação não é teórico, é operacional: exige guardar as observações no nível da unidade de sorteio, e não só os totais agregados. Quem só tem “visitantes e conversões” numa planilha não consegue permutar nada, porque a informação individual já foi jogada fora na agregação.
A Donnu guarda o evento no nível do usuário sorteado, então a distribuição nula empírica é calculável sobre qualquer métrica do experimento, não só sobre a taxa de conversão. Na prática isso significa poder ler uma rampa de 1 por cento sem o viés de 16 por cento de falso positivo que a tabela deste artigo mostra, e poder testar diferença de mediana sem inventar uma fórmula para ela. Se você está começando agora, comece pelo mais barato: rode a calculadora de significância e, se a contagem for baixa, confira com Yates antes de decidir.
Referências
- Guo, W., Lee, J. e Toulis, P. ML-assisted Randomization Tests for Detecting Treatment Effects in A/B Experiments. arXiv 2501.07722, janeiro de 2025. Fonte do enquadramento de que a inferência por aleatorização remonta a Fisher (1935), de que os procedimentos do tipo teste de aleatorização de Fisher são válidos em amostra finita para distribuições arbitrárias por explorarem a variação conhecida na atribuição dos tratamentos, e de que esses testes são normalmente implementados como testes de permutação em experimentação online. arxiv.org.
- Phipson, B. e Smyth, G. K. Permutation P-values Should Never Be Zero: Calculating Exact P-values When Permutations Are Randomly Drawn. Statistical Applications in Genetics and Molecular Biology, volume 9, número 1, artigo 39, 2010. Fonte da demonstração de que o valor-p ingênuo é subestimado em cerca de 1 sobre o número de permutações e de que substituir o valor-p exato por um estimador não viesado aumenta a taxa de erro tipo I; do argumento de que a permutação deve ser vista como geradora de uma distribuição nula discreta exata, e não como estimativa de uma probabilidade de cauda; e do registro histórico de que a enumeração completa é de Fisher (1935), o sorteio de um subconjunto de permutações é de Dwass (1957) e o teste Monte Carlo é de Barnard (1963). arxiv.org.
- Kohavi, R., Deng, A., Longbotham, R. e Xu, Y. Seven Rules of Thumb for Web Site Experimenters. KDD 2014. Fonte da regra de bolso de 355 vezes o quadrado do coeficiente de assimetria como mínimo de observações independentes para a média ter distribuição aproximadamente normal, com a recomendação de usá-la quando o módulo da assimetria passa de 1; da tabela de métricas do Bing (receita por usuário com assimetria 17,9 e 114 mil observações, receita por usuário com teto com 5,2 e 9,7 mil, sessões por usuário com 3,6 e 4,70 mil, tempo até o sucesso com 2,1 e 1,55 mil); da observação de que aplicar teto em receita por usuário derrubou a assimetria de 18 para 5,3 e permitiu detectar uma mudança 30 por cento menor com a mesma amostra; e da ressalva de que com divisão de tamanhos iguais a distribuição da diferença fica aproximadamente simétrica e a regra deixa de dar limite inferior útil. exp-platform.com.
- Deng, A., Knoblich, U. e Lu, J. Applying the Delta Method in Metric Analytics: A Practical Guide with Novel Ideas. KDD 2018. Fonte do contexto de por que plataformas de experimentação em escala buscam estimadores analíticos de variância em vez de reamostragem, e de por que o custo computacional do bootstrap é o obstáculo prático à sua adoção em produção. arxiv.org.
Leia também: Significância estatística em teste A/B · Outliers e capping · Unidade de sorteio · CRO para sites de baixo tráfego · SRM e divisão desigual · Calculadora de significância · Read in English
Perguntas frequentes
- O que é um teste de permutação em teste A/B?
- É um jeito de calcular o valor-p sem usar fórmula fechada. Você junta as observações dos dois grupos num único balde, sorteia repetidas vezes quais delas ficariam no controle e quais na variação, recalcula a diferença em cada sorteio e vê em que fração dos sorteios a diferença embaralhada foi tão grande quanto a que você observou de verdade. Essa fração é o valor-p. A ideia é de Fisher, em 1935, e é a mesma aleatorização que você já usou para montar o experimento.
- Quando o teste de permutação muda o resultado de um teste A/B?
- Quando a aproximação normal do teste z está ruim. Isso acontece em duas situações típicas: contagens pequenas (dezenas de conversões, não milhares) e divisão de tráfego muito desigual em métrica assimétrica, como uma rampa de 1 por cento em receita por usuário. Na simulação deste artigo, com divisão 99/1, o teste z rejeitou 16,44 por cento dos testes A/A a um alfa nominal de 5 por cento, e o teste de permutação rejeitou 4,78 por cento.
- Quantas permutações são necessárias?
- Depende da precisão que você quer perto do seu limiar de decisão. Com 10.000 permutações, o erro-padrão de um valor-p perto de 0,05 é 0,0022, ou seja, o intervalo de 95 por cento em torno da estimativa tem meia largura de 0,0043. Com 1.000 permutações essa meia largura sobe para 0,0135, larga demais para decidir em cima de 0,05. Para publicar um valor-p abaixo de 0,001 você precisa de pelo menos 999 permutações, porque o menor valor possível é 1 dividido por (B mais 1).
- Por que somar 1 no numerador e no denominador do valor-p?
- Porque a estatística observada é ela própria uma das permutações possíveis. Phipson e Smyth mostraram que a conta ingênua, dividir a contagem pelo número de permutações, subestima o valor-p em cerca de 1 sobre o número de permutações e aumenta o erro tipo I do teste. A forma correta é somar 1 aos dois: (b mais 1) dividido por (B mais 1). Isso também impede o resultado absurdo de um valor-p exatamente zero.
- Teste de permutação resolve viés de amostragem ou SRM?
- Não. Ele conserta a aproximação da distribuição nula, e só isso. Se o sorteio quebrou, se um dos grupos perdeu eventos por falha de rastreamento ou se existe interferência entre as variações, os dados já estão contaminados antes da conta, e embaralhar rótulos contaminados devolve um valor-p corretamente calculado sobre um experimento errado. A hipótese que o teste de permutação exige é a de permutabilidade sob a nula, e ela cai junto com o sorteio.
- Qual a diferença entre permutação e bootstrap?
- A permutação embaralha rótulos sem repor e responde uma pergunta de teste: qual a chance de ver uma diferença desse tamanho se o rótulo não importasse. O bootstrap reamostra com reposição dentro de cada grupo e responde uma pergunta de estimativa: qual a incerteza em torno do efeito medido. Na prática você usa os dois, permutação para o valor-p e bootstrap para o intervalo de confiança, porque a permutação sozinha não entrega intervalo.