Aula 11 — Módulo 2: Inferência Estatística
Quando uma diferença observada é grande demais para atribuir apenas ao acaso?
Exemplo da aula: taxa de pedidos entregues depois da data prevista.
Um limite operacional considera aceitável uma taxa de atraso de 8%.
Há evidência de que a taxa de atrasos excede 8%?
Precisamos separar diferença real de variação amostral.
late, igual a 1 quando a entrega supera a data prevista;A amostra de 1.200 pedidos será usada para testar uma referência operacional de 8%.
Para cada pedido:
\[ Y_i= \begin{cases} 1, & \text{entregue depois da data prevista}\\ 0, & \text{entregue até a data prevista} \end{cases} \]
O parâmetro \(p=P(Y=1)\) é a taxa populacional de atraso.
\[ \widehat{p}=\frac{1}{n}\sum_{i=1}^{n}Y_i \]
Em uma amostra de 1.200 pedidos:
\[ k=115, \qquad \widehat{p}=115/1200=0{,}0958 \]
Observamos 9,58% de atrasos.
Uma diferença observada precisa ser comparada a essa variabilidade.
prop_means = np.array([rng.choice(late, size=1200, replace=True).mean() for _ in range(5000)])
plt.figure(figsize=(9, 5.2))
sns.histplot(prop_means, bins=30, color=BLUE)
plt.axvline(p_late, color=ORANGE, lw=3, label=f"p = {p_late:.3f}")
plt.xlabel("Proporção de pedidos atrasados")
plt.ylabel("Frequência")
plt.title("A taxa de atraso também varia entre amostras")
plt.legend()
finish("distribuicao-taxa-atraso.png")
# Amostra observada usada na Aula 11.
obs = np.random.default_rng(13).choice(late, 1200, replace=False)
k_obs = int(obs.sum())
p_hat = obs.mean()
p0 = .08
se0 = np.sqrt(p0 * (1 - p0) / len(obs))
z_obs = (p_hat - p0) / se0“A taxa parece alta” é ambíguo.
Um teste exige:
A hipótese nula representa o valor de referência:
\[ H_0:p=0{,}08 \]
Ela é o modelo que usamos para calcular quão surpreendente é a amostra.
Nossa pergunta é direcional:
\[ H_1:p>0{,}08 \]
Se a pergunta fosse “diferente de 8%”, usaríamos:
\[ H_1:p\neq0{,}08 \]
Sob \(H_0\), o número de atrasos segue:
\[ K\sim\operatorname{Binomial}(n=1200,p=0{,}08) \]
Logo:
\[ E[\widehat{p}]=0{,}08, \quad \operatorname{SE}_0=\sqrt{\frac{0{,}08(0{,}92)}{1200}} \]
\(K\) é o número de atrasos em \(n\) pedidos; \(p_0=0{,}08\) é o valor imposto por \(H_0\); \(\widehat p=K/n\) é a proporção amostral. O índice zero em \(\operatorname{SE}_0\) indica que o erro padrão é calculado sob a hipótese nula.
O valor observado está à direita do centro previsto por \(H_0\).
null_props = rng.binomial(len(obs), p0, size=12000) / len(obs)
plt.figure(figsize=(9, 5.2))
sns.histplot(null_props, bins=30, color=BLUE)
plt.axvline(p_hat, color=ORANGE, lw=3, label=f"p̂ observado = {p_hat:.3f}")
plt.axvline(p0, color=INK, lw=2, ls="--", label="H0: p = 0,08")
plt.xlabel("Proporção de atrasos sob H0")
plt.ylabel("Simulações")
plt.title("A hipótese nula prevê resultados possíveis")
plt.legend()
finish("distribuicao-nula.png")Padronizamos a distância até o valor nulo:
\[ Z=\frac{\widehat{p}-p_0} {\sqrt{p_0(1-p_0)/n}} \]
\(Z\) mede quantos erros padrão separam a amostra de \(H_0\): \(\widehat p\) é a taxa observada, \(p_0\) é a taxa nula e \(n\) é o tamanho amostral. Sob \(H_0\) e condições adequadas, \(Z\approx N(0,1)\).
\[ Z= \frac{0{,}0958-0{,}08} {\sqrt{0{,}08(0{,}92)/1200}} =2{,}02 \]
Se \(H_0\) fosse verdadeira, a estimativa estaria 2,02 erros padrão acima do esperado.
Para o teste unilateral:
\[ p\text{-valor}=P(Z\ge2{,}02\mid H_0) \]
Neste exemplo:
\[ p\text{-valor}\approx0{,}0216 \]
A probabilidade é calculada assumindo \(H_0\). O evento \(Z\ge2{,}02\) reúne resultados pelo menos tão favoráveis a \(H_1\) quanto o observado; não é a probabilidade de \(H_0\) ser verdadeira.
Contamos resultados tão ou mais favoráveis a \(H_1\) que o observado.
counts, bins = np.histogram(null_props, bins=30)
centers = (bins[:-1] + bins[1:]) / 2
plt.figure(figsize=(9, 5.2))
colors = [ORANGE if c >= p_hat else BLUE for c in centers]
plt.bar(centers, counts, width=np.diff(bins), color=colors, align="center")
plt.axvline(p_hat, color=INK, lw=3)
plt.xlabel("Proporção de atrasos sob H0")
plt.ylabel("Simulações")
plt.title("O p-valor é a cauda tão extrema quanto o observado")
finish("pvalor-cauda.png")É uma probabilidade calculada assumindo \(H_0\).
Um valor-p de 0,02 significa que:
Escolhemos antes do teste um limite \(\alpha\) para o erro tipo I.
Regra comum:
\[ p\text{-valor}<\alpha\quad\Rightarrow\quad\text{rejeitar }H_0 \]
Com \(\alpha=0{,}05\), rejeitaríamos \(H_0\) neste exemplo.
Reduzir \(\alpha\) exige uma estatística mais extrema.
xz = np.linspace(-4, 4, 500)
pdf = np.exp(-xz**2 / 2) / np.sqrt(2 * np.pi)
fig, axes = plt.subplots(1, 2, figsize=(11, 4.5), sharey=True)
for ax, cutoff, alpha in [(axes[0], 1.645, "5%"), (axes[1], 2.326, "1%")]:
ax.plot(xz, pdf, color=BLUE, lw=3)
ax.fill_between(xz, 0, pdf, where=xz >= cutoff, color=ORANGE, alpha=.65)
ax.axvline(cutoff, color=INK, ls="--")
ax.set_title(f"α = {alpha}")
ax.set_xlabel("Estatística z")
axes[0].set_ylabel("Densidade sob H0")
fig.suptitle("Reduzir α exige evidência mais extrema", fontweight="bold")
finish("regioes-rejeicao.png")Conclusão adequada:
Os dados fornecem evidência contra uma taxa de atraso de 8%, em favor de uma taxa maior.
Evite:
Provamos que a taxa verdadeira é maior que 8%.
Um resultado não significativo pode ocorrer porque:
“Ausência de evidência” não é “evidência de ausência”.
Em um teste bilateral com \(\alpha=5\%\):
O intervalo acrescenta uma faixa de efeitos plausíveis.
Sob \(H_0\):
\[ K\sim\operatorname{Binomial}(1200,0{,}08) \]
O p-valor exato unilateral é:
\[ P(K\ge115\mid p=0{,}08)=\boxed{0{,}0268} \]
Não precisamos aproximar uma variável discreta por uma Normal.
Correção de continuidade
A massa do inteiro \(k\) é representada pela área da Normal entre os dois pontos médios adjacentes.
\[ P(K\le k)\approx P(Y\le k+0{,}5), \qquad P(K\ge k)\approx P(Y\ge k-0{,}5). \]
from math import comb, pi, sqrt
n, p = 10, 0.5
k = np.arange(n + 1)
pmf = np.array([comb(n, int(i)) * p**i * (1-p)**(n-i) for i in k])
mu, sigma = n*p, np.sqrt(n*p*(1-p))
x = np.linspace(-0.5, 10.5, 1200)
pdf = np.exp(-0.5*((x-mu)/sigma)**2) / (sigma*np.sqrt(2*pi))
plt.bar(k, pmf, width=.86, color=[ORANGE if i >= 7 else "#c9d8df" for i in k])
plt.plot(x, pdf, color=TEAL, linewidth=3)
plt.fill_between(x, 0, pdf, where=x >= 6.5, color=ORANGE, alpha=.20)
plt.axvline(6.5, color=ORANGE, linestyle="--")As condições valem: \(np_0=96\ge10\) e \(n(1-p_0)=1.104\ge10\). Sob \(H_0\), \(Y\) tem média 96 e variância \(1200(0{,}08)(0{,}92)=88{,}32\).
Aplicação da regra
Queremos a cauda superior \(P(K\ge115)\). Para incluir toda a massa do inteiro 115, a área contínua começa na borda esquerda desse valor:
\[ P(K\ge115)\approx P(Y\ge114{,}5). \]
\[ z_{cc}=\frac{114{,}5-96}{\sqrt{1200(0{,}08)(0{,}92)}}=1{,}97 \]
\[ P(Z\ge1{,}97)=\boxed{0{,}0245} \]
Também podemos gerar 100 mil amostras com \(p=0{,}08\):
\[ p\text{-valor}_{\mathrm{sim}} =\frac{1+\#\{K_b\ge115\}}{100000+1} =\boxed{0{,}0265} \]
O acréscimo de 1 evita um p-valor simulado igual a zero. \(K_b\) é o número de atrasos na simulação \(b\) sob \(H_0\).
Simulação torna a lógica visível e generaliza para estatísticas complexas.
| Método | Vantagem | Limite |
|---|---|---|
| Exato | sem aproximação | pode ser difícil |
| Normal/TCL | fórmula rápida | depende de condições |
| Simulação | flexível e visual | tem erro Monte Carlo |
Resultados próximos aumentam nossa confiança na implementação.
| Realidade | Não rejeitar \(H_0\) | Rejeitar \(H_0\) |
|---|---|---|
| \(H_0\) verdadeira | decisão correta | erro tipo I |
| \(H_1\) verdadeira | erro tipo II | decisão correta |
Não existe regra que elimine os dois erros simultaneamente.
Rejeitar \(H_0\) quando ela é verdadeira.
No contexto:
Concluir que a taxa excede 8% quando ela é exatamente 8%.
Sua probabilidade é controlada por \(\alpha\).
Para um teste calibrado com nível exato \(\alpha\):
\[ \boxed{P_{H_0}(\text{rejeitar }H_0)=\alpha} \]
Interpretação. Se \(H_0\) for verdadeira e repetirmos o estudo, rejeitaremos \(H_0\) em uma fração \(\alpha\) das repetições. O símbolo \(P_{H_0}\) indica que a probabilidade é calculada supondo \(H_0\) verdadeira.
Precisão matemática. Em geral, um teste de nível \(\alpha\) garante
\[ P_{H_0}(\text{rejeitar }H_0)\leq\alpha. \]
Testes discretos podem ser conservadores. A igualdade vale quando o teste usa exatamente todo o nível \(\alpha\).
Com \(H_0\) verdadeira, cerca de 5% dos testes rejeitam por acaso quando \(\alpha=5\%\).
rejections = []
running = []
for i in range(1, 5001):
ph = rng.binomial(1200, p0) / 1200
z = (ph - p0) / se0
rejections.append(z > 1.645)
running.append(np.mean(rejections))
plt.figure(figsize=(9, 5.2))
plt.plot(running, color=BLUE, lw=2)
plt.axhline(.05, color=ORANGE, lw=3, ls="--", label="α = 5%")
plt.xlabel("Número de testes simulados sob H0")
plt.ylabel("Fração de rejeições")
plt.title("Sob H0, rejeitamos cerca de alpha das vezes")
plt.legend()
finish("erro-tipo-i.png")Um \(\alpha\) menor:
A escolha deve refletir o custo dos erros.
Não rejeitar \(H_0\) quando \(H_1\) é verdadeira.
No contexto:
Não detectar uma taxa realmente superior a 8%.
Sua probabilidade é \(\beta\).
\[ \text{poder}=1-\beta \]
Aqui, \(\beta=P_{\theta_1}(\text{não rejeitar }H_0)\) é a probabilidade de erro tipo II sob um valor alternativo específico \(\theta_1\). Portanto, \(1-\beta=P_{\theta_1}(\text{rejeitar }H_0)\).
O poder depende do valor verdadeiro sob a alternativa.
Mantendo \(p_0=8\%\), \(p_1=10\%\) e \(\alpha=5\%\), aumentar \(n\) estreita as duas distribuições. A área de \(H_1\) além do limiar crítico cresce de 37% para 79%.
p0, p1, alpha = .08, .10, .05
z_critical = norm.ppf(1 - alpha)
fig, axes = plt.subplots(1, 2, figsize=(13.2, 5.3), sharex=True)
common_x = np.linspace(.02, .16, 800)
for ax, n in zip(axes, [300, 1200]):
se0 = np.sqrt(p0 * (1-p0) / n)
se1 = np.sqrt(p1 * (1-p1) / n)
critical = p0 + z_critical * se0
x = common_x
y0, y1 = norm.pdf(x, p0, se0), norm.pdf(x, p1, se1)
power = norm.sf(critical, p1, se1)
ax.plot(100*x, y0, color=BLUE, lw=3, label=r"Sob $H_0$: $p=8\%$")
ax.plot(100*x, y1, color=ORANGE, lw=3, label=r"Sob $H_1$: $p=10\%$")
mask = x >= critical
ax.fill_between(100*x[mask], 0, y1[mask], facecolor="#f6c49a",
edgecolor=ORANGE, alpha=.65, hatch="///",
label=f"Poder = {power:.0%}")
ax.axvline(100*critical, color=INK, ls="--", lw=2,
label="limiar crítico")
ax.set(title=f"n = {n} pedidos",
xlabel="Proporção amostral de atrasos (%)")
ax.set_xlim(2, 16)
ax.set_yticks([]); ax.legend(frameon=False)
plt.tight_layout()
finish("poder-duas-distribuicoes.png")Na figura, o efeito permanece de 8% para 10%, mas \(n\) cresce de 300 para 1.200. Por que o poder aumenta?
É mais fácil detectar 12% que 8,5% de atrasos.
true_ps = np.linspace(.05, .13, 33)
critical = p0 + 1.645 * se0
power = []
for p in true_ps:
simulated = rng.binomial(1200, p, size=5000) / 1200
power.append(np.mean(simulated > critical))
plt.figure(figsize=(9, 5.2))
plt.plot(true_ps, power, color=BLUE, lw=3)
plt.axvline(p0, color=INK, ls="--", lw=2)
plt.axhline(.8, color=ORANGE, ls="--", lw=2, label="80% de poder")
plt.xlabel("Taxa verdadeira de atraso")
plt.ylabel("Probabilidade de rejeitar H0")
plt.title("O poder cresce quando o efeito se afasta de H0")
plt.legend()
finish("curva-poder.png")Com mais observações:
Planejar \(n\) exige definir o menor efeito relevante.
A diferença observada foi:
\[ 0{,}0958-0{,}08=0{,}0158 \]
Ou 1,58 ponto percentual.
Pergunta operacional: essa diferença justifica uma ação?
O resultado seria raro sob \(H_0\)?
O efeito tem magnitude e consequência relevantes?
Sempre reporte estimativa e intervalo, não apenas p-valor.
Experiência atualmente usada. Ela fornece a referência para a comparação.
Uma única mudança planejada em relação ao controle.
Distribui unidades entre A e B antes de observar a resposta.
O efeito é causal quando a randomização e o acompanhamento são preservados.
Imagine que a operação desenvolveu um alerta preventivo de risco de atraso para pedidos elegíveis.
O pedido segue o fluxo logístico normalmente usado.
Um alerta antecipado permite priorizar pedidos com maior risco operacional.
Pedidos seriam atribuídos aleatoriamente aos dois processos. A base Olist original é observacional: os números a seguir formam um experimento didático simulado, calibrado por suas taxas de atraso.
Pergunta: o alerta reduz a probabilidade de um pedido chegar depois da data prevista?
\[ \Delta=p_B-p_A, \qquad H_0:\Delta=0, \qquad H_A:\Delta<0. \]
\(p_A\) e \(p_B\) são as probabilidades de atraso nos dois processos. A alternativa foi definida antes dos dados: valores negativos favorecem o alerta.
Em 5.000 pedidos por grupo, atrasaram 415 em A e 345 em B:
\[ \widehat\Delta=6{,}9\%-8{,}3\%=-1{,}4\text{ p.p.} \]
O efeito observado corresponde a 140 atrasos a menos por 10 mil pedidos:
\[ 0{,}083-0{,}069=0{,}014=\frac{140}{10.000}. \]
A magnitude descreve o efeito observado. Agora precisamos avaliar se uma diferença desse tamanho seria rara caso o alerta não tivesse efeito.
Sob \(H_0:p_A=p_B\), estimamos uma única taxa combinada:
\[ \widehat p_{pool} =\frac{415+345}{5000+5000} =0{,}076 \]
Se não há efeito, A e B compartilham a mesma probabilidade de atraso.
\[ \begin{aligned} EP_0&=\sqrt{0{,}076(1-0{,}076) \left(\frac{2}{5000}\right)} \\ EP_0&\approx0{,}00530 \end{aligned} \]
Ele mede a variação esperada de \(\widehat p_B-\widehat p_A\) quando \(H_0\) é verdadeira.
\[ z=\frac{0{,}069-0{,}083}{0{,}00530} \approx-2{,}64 \]
A diferença observada está 2,64 erros padrão abaixo do valor previsto por \(H_0\).
\[ \begin{aligned} p&=P(Z\leq-2{,}64)=\Phi(-2{,}64) \\ p&\approx0{,}0041 \end{aligned} \]
Como \(H_A:p_B-p_A<0\), resultados mais extremos ficam na cauda esquerda.
Se \(H_0\) fosse verdadeira, uma redução igual ou maior que a observada ocorreria em cerca de 0,41% de experimentos como este.
O valor-p aproximado é \(0{,}0041\), menor que \(\alpha=0{,}05\). Portanto, rejeitamos \(H_0\) e encontramos evidência de que o alerta reduz a taxa de atraso.
Isso não encerra a decisão: também precisamos avaliar se 140 atrasos evitados por 10 mil pedidos compensam o custo do alerta e se nenhuma métrica de proteção piorou.
Se fazemos 20 testes independentes com \(\alpha=5\%\):
\[ P(\text{ao menos um falso positivo}) =1-0{,}95^{20}\approx64\% \]
São estratégias complementares — apenas a segunda é uma correção matemática:
Definir hipóteses, desfechos e análises antes de observar os resultados reduz escolhas oportunistas.
Ajustar o limiar ou os valores-p (por exemplo, Bonferroni ou Holm) controla o erro da família de testes.
Verificar o achado em novos dados independentes testa se ele se repete fora da amostra original.
Use unilateral somente quando:
Caso contrário, prefira o teste bilateral.
Verifique:
Em um A/B, acrescente antes da coleta: unidade de randomização, versão de controle, mudança aplicada, métrica primária, duração e regra de parada.
Em 800 pedidos, 76 atrasaram. Teste \(H_0:p=0{,}08\) contra \(H_1:p>0{,}08\).
Inferência não elimina a incerteza; ela torna explícito como decidimos dentro dela.
Boas conclusões combinam desenho, estimativa, intervalo, p-valor e consequência prática.
olistbr/brazilian-ecommerce.ICD: Aula 11 — Testes de hipótesesvoltar para a Aula