Maturidade de Coorte em Teste A/B: ler D7 e D30
Quem entrou ontem não teve 7 dias para ficar. Como a maturidade de coorte distorce retenção D7 e D30, e como fechar a coorte sem perder o teste A/B.

📚 Este artigo faz parte do guia Significância Estatística em Teste A/B: O Guia.
Num teste com entrada contínua de tráfego, o usuário que entrou ontem não teve sete dias para ficar, e mesmo assim ele entra na conta de retenção D7 como se tivesse tido. Na simulação deste guia isso derrubou a retenção lida de 29,5404 para 23,2103 por cento, e num cenário com lançamento em rampa chegou a inverter o vencedor: menos 5,99 por cento na leitura ingênua contra mais 8,22 por cento na leitura correta. Este guia mostra como a maturidade de coorte se forma, quando ela só erra o nível e quando ela erra o veredito, e como fechar a coorte sem inviabilizar o teste. Faz parte do nosso guia completo de teste A/B e complementa atraso de conversão e métricas de tempo até o evento.
O problema: o teste tem um começo, o usuário tem outro
Um experimento clínico recruta os participantes antes de começar. Todo mundo entra junto, todo mundo é acompanhado pelo mesmo período, e a métrica “sobreviveu 30 dias?” significa a mesma coisa para todos.
Teste A/B online não funciona assim. Kohavi, Deng, Frasca, Longbotham, Walker e Xu registram o ponto de forma direta: ao contrário da maioria dos experimentos offline, experimentos online recrutam usuários continuamente, em vez de terem um período de recrutamento antes do experimento, e como consequência o tamanho de amostra cresce enquanto o experimento roda.
Isso é uma virtude operacional e um problema de medição. Cada usuário tem um relógio próprio, que começa no dia em que ele entrou. Num teste de 28 dias:
- quem entrou no dia 1 tem 28 dias de acompanhamento
- quem entrou no dia 14 tem 15
- quem entrou no dia 27 tem 2
- quem entrou no dia 28 tem 1
Agora aplique a isso a métrica mais comum de produto: retenção em D7. Ela pergunta se o usuário estava ativo sete dias depois de entrar. Para quem entrou no dia 27, essa pergunta simplesmente não tem resposta ainda.
E aí acontece o erro que dá nome a este artigo: a consulta padrão soma “usuários retidos em D7” no numerador e “usuários que entraram no teste” no denominador. Quem não teve sete dias entra no denominador e não pode entrar no numerador. Ele não é contado como dado faltante, é contado como fracasso.
Caso 1: os dois braços recrutam igual, e só o nível quebra
Simulamos um teste de 28 dias, com 900 novos usuários por braço por dia, totalizando 25.200 por braço. A verdade do mundo simulado: retenção D7 de 30,00 por cento no controle e 32,40 por cento na variação, ou seja, a variação é 8 por cento melhor em termos relativos.
Os dois braços recrutam no mesmo ritmo, todo dia, sem rampa.
| leitura | controle | variação | lift relativo | z | valor-p | IC 95% da diferença |
|---|---|---|---|---|---|---|
| ingênua (denominador = todos os inscritos) | 5.849 / 25.200 (23,2103%) | 6.484 / 25.200 (25,7302%) | +10,86% | 6,5793 | abaixo de 1e-10 | [1,7695 pp; 3,2702 pp] |
| coorte fechada (denominador = quem teve 7 dias) | 5.849 / 19.800 (29,5404%) | 6.484 / 19.800 (32,7475%) | +10,86% | 6,8908 | abaixo de 1e-11 | [2,2954 pp; 4,1187 pp] |
Confira as duas linhas na calculadora, colando os quatro números de cada uma:
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.
Duas leituras da tabela, e a segunda é a que interessa.
O nível está errado por 6,3301 pontos. A leitura ingênua devolve 23,2103 por cento de retenção D7 onde o valor real é 29,5404 por cento. Isso é uma subestimação de 21,43 por cento do valor verdadeiro, e não é coincidência: 21,43 por cento é exatamente a fração da amostra que está imatura (5.400 de 25.200). O viés de nível é aritmeticamente igual à fração imatura, porque cada usuário imaturo entra como um zero garantido.
O lift relativo, por outro lado, sobreviveu. Os dois braços perderam a mesma fração, então a razão entre as taxas é a mesma nas duas linhas: mais 10,86 por cento em ambas. Só o intervalo de confiança muda, e para melhor na leitura fechada, porque o denominador menor é também mais honesto.
Vale registrar que o lift observado de mais 10,86 por cento fica acima da verdade de mais 8,00 por cento. Isso é ruído amostral comum, não viés: o intervalo de confiança da leitura fechada, de 2,2954 a 4,1187 pontos, contém a diferença verdadeira de 2,40 pontos sem apertar.
Então, quando os dois braços recrutam igual, a maturidade de coorte é um problema de nível, não de comparação. E problema de nível ainda é problema:
- comparar 23,21 por cento com uma meta de 30 por cento acusa fracasso onde há sucesso
- comparar com o histórico da empresa, medido em outra duração, compara coisas diferentes
- comparar com um benchmark de mercado é chute puro
- projetar receita a partir de uma retenção subestimada em 21 por cento erra a projeção em 21 por cento
Caso 2: um braço em rampa, e o veredito inverte
Agora a versão perigosa. Mesmo teste, mesma verdade (variação 8 por cento melhor), com uma única mudança: a variação foi liberada em rampa, ou seja, com 10 por cento do tráfego na primeira semana, 60 por cento na segunda e 100 por cento depois.
Isso não é um cenário exótico. É rollout progressivo, a prática recomendada para reduzir risco de lançamento, e a mais comum em times que usam feature flags.
| leitura | controle | variação | lift relativo | z | valor-p | IC 95% da diferença |
|---|---|---|---|---|---|---|
| ingênua | 5.941 / 25.200 (23,5754%) | 3.770 / 17.010 (22,1634%) | menos 5,99% | menos 3,3808 | 0,000723 | [menos 2,2270 pp; menos 0,5969 pp] |
| coorte fechada | 5.941 / 19.800 (30,0051%) | 3.770 / 11.610 (32,4720%) | mais 8,22% | 4,5666 | 0,000005 | [1,4025 pp; 3,5314 pp] |
Leia com calma, porque as duas linhas são o mesmo teste, os mesmos usuários e os mesmos eventos.
A leitura ingênua diz que a variação perdeu por 5,99 por cento, com valor-p de 0,000723. É significativa. Um time disciplinado, com plano de análise e limiar de 0,05, mataria essa variação com justificativa formal.
A leitura de coorte fechada diz que a variação ganhou por 8,22 por cento, com valor-p de 0,000005. Também significativa, e o valor está praticamente em cima da verdade de mais 8,00 por cento.
O mecanismo é simples de enunciar depois de visto. A rampa fez a variação recrutar mais tarde, então a coorte dela é mais jovem: só 68,25 por cento dos usuários da variação chegaram a completar sete dias, contra 78,57 por cento do controle. Dez pontos a mais de usuários imaturos, cada um entrando como um zero, derrubam a taxa observada da variação abaixo da do controle.
O elo com SRM, que não substitui esta checagem
Um leitor atento vai reparar que os braços têm tamanhos diferentes, 25.200 contra 17.010, e que isso dispararia um alarme de divisão desigual de tráfego. Está certo, e vale separar as duas coisas com cuidado:
- SRM detecta divisão desigual que você não esperava. Numa rampa planejada, a divisão desigual é o desenho, então o alarme é esperado e você o dispensa conscientemente.
- Dispensar o alarme de SRM não dispensa o problema de maturidade. São coisas diferentes. Você pode ter braços do mesmo tamanho e coortes de idades diferentes, se as entradas se distribuíram de forma diferente ao longo dos dias sem mudar o total.
A checagem certa não é comparar o número de usuários por braço, é comparar a distribuição de datas de entrada por braço. Se as duas distribuições não são iguais, e a métrica tem janela, feche a coorte.
O conserto da maturidade de coorte: fechar a coorte
A regra é uma linha: só entram na análise os usuários que entraram até o dia final do teste menos a janela da métrica. Num teste de 28 dias com métrica D7, analise quem entrou nos primeiros 22 dias. Todo mundo no denominador teve exatamente a mesma oportunidade.
O Spotify usa exatamente esse desenho no corpus de validação da métrica de tempo até a inatividade: Chandar e coautores registram que, em cada experimento, existe um período de entrada de 7 dias e apenas usuários expostos durante esse período entram na análise, com a janela posterior à exposição usada para calcular a métrica. A retenção semanal deles na semana 2, por exemplo, usa os dados dos 14 dias desde a exposição, não os 14 primeiros dias do calendário do teste.
O que isso custa em amostra
| duração do teste | fração aproveitável para métrica D7 | fração aproveitável para métrica D30 |
|---|---|---|
| 10 dias | 40,00% | 0,00% |
| 14 dias | 57,14% | 0,00% |
| 21 dias | 71,43% | 0,00% |
| 28 dias | 78,57% | 0,00% |
| 35 dias | 82,86% | 17,14% |
| 42 dias | 85,71% | 30,95% |
| 56 dias | 89,29% | 48,21% |
A linha que mais surpreende times é a de D30: um teste de 28 dias tem zero por cento de amostra aproveitável para uma métrica de 30 dias. Nenhum usuário teve trinta dias. Se o seu relatório mostra retenção D30 de um teste de quatro semanas, aquele número foi construído de alguma forma que não é a que o nome sugere.
E o custo em recrutamento, usando o mesmo cenário da simulação (base de 30,00 por cento, detectar mais 8,00 por cento relativo, 95 por cento de confiança e 80 por cento de poder):
| duração do teste | N por variação exigido pela estatística | usuários a recrutar por variação |
|---|---|---|
| 14 dias | 5.849 | 10.236 |
| 28 dias | 5.849 | 7.445 |
| 42 dias | 5.849 | 6.824 |
O padrão é claro e é útil na hora de negociar prazo: a perda por imaturidade cai rápido nos primeiros dias e depois estagna. Ir de 14 para 28 dias economiza 2.791 usuários por variação; ir de 28 para 42 economiza só mais 621. O ponto de virada costuma estar entre três e quatro vezes a janela da métrica.
Para rodar essa conta com os seus números, use a calculadora de tamanho de amostra para obter o N e depois divida pela fração aproveitável da tabela acima. A calculadora de duração fecha o ciclo com o tráfego semanal real.
Rodar mais tempo resolve tudo? Não
Existe uma leitura otimista deste artigo que diz “então é só rodar mais tempo”. Ela é parcialmente verdadeira e vale corrigir, porque Kohavi e coautores mediram exatamente o limite dessa ideia.
Para métricas limitadas, como taxa de clique, o intervalo de confiança do efeito percentual realmente encolhe com a duração, e rodar mais tempo aumenta o poder. Mas para métricas como sessões por usuário eles observaram que o intervalo de confiança do efeito percentual não encolhe com o tempo. A explicação é que a largura do intervalo é governada pelo coeficiente de variação dividido pela raiz do tamanho de amostra, e o coeficiente de variação dessas métricas cresce ao longo do experimento, porque o desvio-padrão cresce mais rápido que a média. Nos dados deles, a razão entre coeficiente de variação e raiz da amostra ficou praticamente constante ao longo de 31 dias, com variação menor que 10 por cento.
A tradução prática, nas palavras deles: para métricas como sessões por usuário, o poder estatístico não necessariamente aumenta conforme o experimento roda mais tempo, e quando se quer detectar efeito nessas métricas é preciso rodar com mais usuários por dia, não com mais dias.
Então a resposta correta é uma combinação:
- contra imaturidade de coorte, mais dias ajudam, e a tabela acima diz quanto
- contra variância de métrica de contagem, mais dias não ajudam, e o que ajuda é mais tráfego por dia
- contra efeito novidade, só mais dias ajudam, e é essa a razão que Kohavi e coautores dão para rodar mais de uma semana mesmo quando o poder não melhora
Rodar semanas inteiras continua obrigatório pelo motivo de sempre, o efeito de dia da semana, tratado em ciclo semanal. Uma semana é o mínimo para enxergar esse efeito.
Roteiro de maturidade de coorte em cinco passos
- Para toda métrica com janela, escreva a janela. “Retenção” não é uma métrica; “ativo entre o dia 6 e o dia 8 após a entrada” é. Sem isso, ninguém sabe se a coorte está madura.
- Compare a distribuição de datas de entrada entre os braços, não só o total por braço. Um histograma resolve. Distribuições diferentes com métrica de janela significam coorte fechada obrigatória.
- Fixe a regra de corte no plano de análise, antes de rodar. Escolher entre leitura ingênua e leitura fechada depois de ver as duas é escolher o resultado.
- Reporte o denominador junto da taxa. “29,54 por cento de retenção D7 sobre 19.800 usuários maduros de 25.200 inscritos” é uma frase completa. “23,2 por cento de retenção” não é.
- Dimensione o teste com a fração aproveitável já descontada. O N que a calculadora devolve é o que você precisa analisar, não o que precisa expor.
Erros comuns
- Usar o total de inscritos como denominador de uma métrica com janela. O erro central. Ele transforma dado faltante em fracasso.
- Confiar no lift relativo porque “o viés atinge os dois lados”. Só atinge igualmente se os dois lados recrutaram igual. Rampa, liberação por região, cota por plano e correção de bug no meio do teste quebram essa premissa.
- Achar que a checagem de SRM cobre isso. Ela compara tamanhos, não idades. Braços do mesmo tamanho podem ter distribuições de entrada diferentes.
- Reportar D30 de um teste de 28 dias. Não existe. Se aparece um número, ele veio de outra definição, e essa definição precisa estar escrita.
- Comparar a retenção de um teste com a retenção do painel de produto. O painel costuma usar coorte fechada e o teste costuma não usar. A diferença de nível não é o efeito, é a definição.
- Descartar coorte imatura sem dizer quanto foi descartado. Fechar a coorte é correto e reduz a amostra; omitir isso do relatório transforma um método em mágica.
- Tratar isso como sinônimo de atraso de conversão. São primos e não gêmeos: atraso de conversão é o evento que ainda vai chegar; maturidade de coorte é a janela de observação que ainda não fechou. O conserto se parece, a causa não.
Faça isso automático na Donnu
O motivo de essa distorção passar batida quase nunca é falta de rigor, é a forma do dado: a maioria dos painéis de teste A/B guarda um sinalizador de conversão ou retenção por usuário e não guarda a data de entrada dele no experimento. Sem a data de entrada não existe idade de coorte, e sem idade de coorte não existe como fechar a coorte.
A Donnu guarda a data de sorteio de cada usuário junto do resultado dele, o que torna a leitura de coorte fechada um filtro e não uma reconstrução. Se a sua montagem atual não guarda, o passo imediato é começar a gravar a data de entrada hoje, e enquanto isso adotar a regra conservadora: para qualquer métrica com janela, só ler o teste depois de decorrida a janela contada a partir da última entrada. Para dimensionar o teste já com o desconto da coorte imatura, a calculadora de tamanho de amostra dá o N e a tabela deste artigo dá o divisor.
Referências
- Kohavi, R., Deng, A., Frasca, B., Longbotham, R., Walker, T. e Xu, Y. Trustworthy Online Controlled Experiments: Five Puzzling Outcomes Explained. KDD 2012, Microsoft. Fonte do ponto de que experimentos online recrutam usuários continuamente, em vez de terem um período de recrutamento antes do experimento, e de que o tamanho de amostra cresce enquanto o experimento roda; do achado de que, para métricas como sessões por usuário, o intervalo de confiança do efeito percentual não encolhe com o tempo e o poder estatístico não necessariamente aumenta com a duração; da explicação de que a largura do intervalo é governada pelo coeficiente de variação dividido pela raiz do tamanho de amostra e de que esse coeficiente cresce ao longo do experimento porque o desvio-padrão cresce mais rápido que a média; da medida de que a razão entre coeficiente de variação e raiz da amostra variou menos de 10 por cento ao longo de 31 dias; da recomendação de rodar com mais usuários por dia nesses casos; e da razão para rodar mais de uma semana mesmo assim, que é o risco de efeito de primazia e novidade, com uma semana como mínimo para enxergar efeito de dia da semana. exp-platform.com.
- Chandar, P., St. Thomas, B., Maystre, L., Pappu, V., Sanchis-Ojeda, R., Wu, T., Carterette, B., Lalmas, M. e Jebara, T. Using Survival Models to Estimate User Engagement in Online Experiments. WWW 2022, Spotify. Fonte do desenho de coorte de entrada fechada: em cada experimento do corpus existe um período de entrada de 7 dias e apenas os usuários expostos durante esse período entram na análise, com a janela posterior à exposição usada para calcular a métrica, de modo que a retenção semanal da semana 2 usa os dados dos 14 dias desde a exposição; e do corpus de 51 testes rodados por pelo menos 28 dias após esse período de entrada. mounia-lalmas.blog.
- Kohavi, R., Deng, A., Frasca, B., Walker, T., Xu, Y. e Pohlmann, N. Online Controlled Experiments at Large Scale. KDD 2013, Microsoft. Fonte da regra de que o placar final do experimento é fechado num múltiplo de semanas, usualmente duas, o que é a restrição de calendário dentro da qual a coorte fechada precisa caber. exp-platform.com.
- Chapelle, O. Modeling Delayed Feedback in Display Advertising. KDD 2014, Criteo Labs. Fonte do custo de esperar a janela fechar: no estudo dele, o tráfego vindo de campanhas novas chega a 11,3 por cento depois de 26 dias, o que mostra que a espera não é gratuita porque o ambiente medido muda enquanto se espera. wnzhang.net.
Leia também: Atraso de conversão · Métricas de tempo até o evento · SRM e divisão desigual · Rollout progressivo · Ciclo semanal · Calculadora de tamanho de amostra · Read in English
Perguntas frequentes
- O que é maturidade de coorte em teste A/B?
- É quanto tempo de acompanhamento cada usuário teve depois de entrar no teste. Num teste com entrada contínua de tráfego, quem entrou no primeiro dia de um teste de 28 dias tem 28 dias de acompanhamento e quem entrou no dia 27 tem um. Uma métrica que exige uma janela fixa, como retenção em D7, só é calculável para quem já completou essa janela.
- Por que a retenção D7 aparece menor do que é de verdade?
- Porque o denominador padrão inclui todo mundo que entrou no teste, inclusive quem ainda não teve sete dias, e essas pessoas entram no cálculo como não retidas por falta de dado, não por comportamento. Na simulação deste guia, a retenção D7 verdadeira era de 29,5404 por cento e a leitura ingênua devolveu 23,2103 por cento, uma subestimação de 6,3301 pontos, ou 21,43 por cento do valor real.
- Se a distorção atinge os dois braços igualmente, o teste continua válido?
- A comparação relativa sobrevive quando os dois braços recrutam no mesmo ritmo. O que não sobrevive é o nível, então qualquer comparação com meta, com histórico ou com benchmark de mercado fica errada. E basta um braço recrutar em ritmo diferente para a comparação também quebrar.
- Como um lançamento em rampa inverte o resultado?
- Porque a rampa deixa a coorte do braço liberado mais tarde sistematicamente mais jovem. Na segunda simulação deste guia, a variação era genuinamente 8 por cento melhor e a leitura ingênua devolveu menos 5,99 por cento com valor-p de 0,000723, ou seja, uma derrota estatisticamente significativa. A mesma leitura restrita à coorte madura devolveu mais 8,22 por cento com valor-p de 0,000005. O sinal inverteu.
- Qual é o conserto?
- Fechar a coorte: só entram na análise os usuários que entraram até o dia final menos a janela da métrica. Num teste de 28 dias com métrica D7, isso significa analisar quem entrou nos primeiros 22 dias, cada um com seus sete dias completos. O custo é a amostra descartada, que nesse exemplo é de 21,43 por cento.
- Quanto tempo a mais o teste precisa rodar?
- A fração aproveitável é a duração do teste menos a janela, mais um, dividida pela duração. Para uma métrica D7, um teste de 14 dias aproveita 57,14 por cento da amostra e um de 42 dias aproveita 85,71 por cento. Na simulação deste guia, o N de 5.849 por variação vira 10.236 usuários a recrutar num teste de 14 dias e 6.824 num de 42.