Testes t para comparar médias
Execute testes t de uma amostra, de duas amostras independentes e pareados com scipy.stats e interprete os intervalos de confiança.
Testes t para comparar médias é uma aula grátis de Pandas & NumPy Academy no CoddyKit. Esta é a aula 2 de 4. Você pode ler a aula completa abaixo gratuitamente — depois pratica ao vivo no navegador com um editor de código integrado e um tutor de IA 24/7. Faz parte do caminho de aprendizado de Pandas & NumPy Academy, e seu progresso é sincronizado entre a web e o app CoddyKit. O curso de Pandas & NumPy Academy inclui 4 aulas no total.
O que é um teste t?
Um teste t é um teste de hipóteses que determina se uma diferença entre as médias de grupos é estatisticamente significativa ou provavelmente se deve ao acaso. Ele compara a diferença observada com a variabilidade dos dados, produzindo uma estatística t e um valor de p. Se p ≤ 0.05 (o limiar convencional), rejeitamos a hipótese nula de que as médias são iguais. Há três tipos comuns: teste t de uma amostra, teste t independente de duas amostras e teste t pareado, cada um destinado a diferentes delineamentos experimentais.
Teste t de uma amostra
O teste t de uma amostra verifica se a média de uma amostra difere significativamente de uma média populacional conhecida ou hipotética. Por exemplo: “Nosso tempo médio de entrega é significativamente diferente do padrão do setor de 3 dias?” Use scipy.stats.ttest_1samp(data, popmean). A hipótese nula é H₀: mean = popmean. Um valor de p pequeno leva à rejeição de H₀ e à conclusão de que a média amostral difere do valor-alvo.
import numpy as np
from scipy import stats
np.random.seed(42)
# Delivery times in days (true mean is ~3.5, not 3)
delivery_times = np.random.normal(loc=3.5, scale=0.8, size=50)
# Test: is our mean significantly different from 3 days?
stat, p = stats.ttest_1samp(delivery_times, popmean=3.0)
print(f'Sample mean: {delivery_times.mean():.3f}')
print(f't-statistic: {stat:.3f}')
print(f'p-value: {p:.4f}')
print('Differs from 3?', 'Yes' if p < 0.05 else 'No')Teste t independente de duas amostras
O teste t de duas amostras independentes compara as médias de dois grupos independentes. Por exemplo: “A variante do teste A/B gera uma receita média maior do que o controle?” Use scipy.stats.ttest_ind(group_a, group_b). O parâmetro equal_var é importante: defina equal_var=False (teste t de Welch) quando os dois grupos puderem ter variâncias diferentes, que é a opção padrão mais segura para a maioria dos dados reais.
import numpy as np
from scipy import stats
np.random.seed(0)
# A/B test revenue per session
control = np.random.normal(loc=25.0, scale=8.0, size=80)
variant = np.random.normal(loc=28.0, scale=9.0, size=80)
# Welch's t-test (does not assume equal variances)
stat, p = stats.ttest_ind(control, variant, equal_var=False)
print(f'Control mean: {control.mean():.2f}')
print(f'Variant mean: {variant.mean():.2f}')
print(f't-statistic: {stat:.3f}')
print(f'p-value: {p:.4f}')
print('Significant difference?', 'Yes' if p < 0.05 else 'No')Testes unicaudais e bicaudais
Por padrão, os testes t são bicaudais: eles verificam se as médias diferem em qualquer direção (maior OR menor). Se tiver uma hipótese direcional (“a variante aumenta a receita”), use um teste unicaudal com o parâmetro alternative: 'greater' ou 'less'. Um teste unicaudal tem mais poder para a direção específica, mas não fornece evidências sobre a outra direção. Decida a direção antes de analisar os dados para evitar HARKing (formular hipóteses depois de conhecer os resultados).
import numpy as np
from scipy import stats
np.random.seed(1)
control = np.random.normal(25, 8, 100)
variant = np.random.normal(27, 8, 100)
# Two-tailed (default): does mean differ at all?
stat, p_two = stats.ttest_ind(control, variant, equal_var=False,
alternative='two-sided')
# One-tailed: is variant > control?
stat, p_one = stats.ttest_ind(control, variant, equal_var=False,
alternative='less')
print(f'Two-tailed p: {p_two:.4f}')
print(f'One-tailed p (variant greater): {p_one:.4f}')Teste t pareado
O teste t pareado é usado quando cada observação do grupo A tem um par natural no grupo B — por exemplo, medições antes e depois de um tratamento nos mesmos indivíduos ou nas mesmas lojas em dois meses diferentes. O pareamento controla a variabilidade entre indivíduos, tornando o teste mais poderoso do que um teste t independente para os mesmos dados. Use scipy.stats.ttest_rel(before, after). A ordem dos elementos deve corresponder: before[i] e after[i] devem vir do mesmo indivíduo.
import numpy as np
from scipy import stats
np.random.seed(5)
# Blood pressure before and after medication (paired)
before = np.random.normal(130, 10, 30)
after = before - np.random.normal(5, 3, 30) # Treatment reduces BP by ~5
stat, p = stats.ttest_rel(before, after)
print(f'Mean before: {before.mean():.2f}')
print(f'Mean after: {after.mean():.2f}')
print(f't-statistic: {stat:.3f}')
print(f'p-value: {p:.4f}')
print('Treatment effective?', 'Yes' if p < 0.05 else 'No')Interpretando a estatística t
A estatística t mede a quantos erros padrão a diferença observada está de zero. Uma estatística t igual a 2 significa que a diferença observada está 2 erros padrão acima do que seria esperado sob a hipótese nula. Para um teste bicaudal com α=0,05 e uma amostra grande, o valor crítico é aproximadamente ±1,96 — portanto, |t| > 1,96 produz p < 0,05. O valor de p converte a estatística t em uma probabilidade, facilitando a interpretação sem consultar tabelas da distribuição t.
import numpy as np
from scipy import stats
# Demonstrate relationship between t-statistic and p-value
for t_val in [1.0, 1.96, 2.5, 3.0, 4.0]:
# degrees of freedom = large sample -> t ~ normal
p = 2 * stats.t.sf(abs(t_val), df=100) # two-tailed
print(f't = {t_val:4.2f} -> p = {p:.4f} '
f'({'significant' if p < 0.05 else 'not significant'})')Intervalos de confiança para a diferença entre médias
Um valor de p, por si só, não informa a magnitude do efeito. Calcule sempre um intervalo de confiança para a diferença entre médias. Um IC de 95% que inclui zero é compatível com p > 0,05 (não significativo); um que não inclui zero significa que a diferença é significativa. O IC também informa se o tamanho do efeito é relevante na prática — uma diferença estatisticamente significativa de US$ 0,01 na receita pode ser irrelevante, enquanto uma diferença de US$ 50 com p=0,06 ainda pode ser importante para o negócio.
import numpy as np
from scipy import stats
np.random.seed(0)
control = np.random.normal(25, 8, 80)
variant = np.random.normal(28, 8, 80)
diff = variant.mean() - control.mean()
se = np.sqrt(control.var()/len(control) + variant.var()/len(variant))
df = len(control) + len(variant) - 2
t_crit = stats.t.ppf(0.975, df=df)
ci_low = diff - t_crit * se
ci_high = diff + t_crit * se
print(f'Mean difference: {diff:.2f}')
print(f'95% CI: [{ci_low:.2f}, {ci_high:.2f}]')
print('CI excludes zero:', ci_low > 0 or ci_high < 0)Tamanho do efeito: d de Cohen
A significância estatística depende do tamanho da amostra — com amostras suficientemente grandes, até diferenças triviais se tornam significativas. O d de Cohen mede a significância prática (tamanho do efeito): a diferença entre médias dividida pelo desvio padrão combinado. Orientações: d < 0,2 é desprezível, 0,2–0,5 é pequeno, 0,5–0,8 é médio e > 0,8 é grande. Relate sempre o tamanho do efeito junto com os valores de p — um valor de p significativo com d = 0,05 significa que a diferença é real, mas provavelmente não é relevante na prática.
import numpy as np
from scipy import stats
np.random.seed(0)
g1 = np.random.normal(25, 8, 200)
g2 = np.random.normal(28, 8, 200)
stat, p = stats.ttest_ind(g1, g2)
# Cohen's d
pooled_std = np.sqrt((g1.var() + g2.var()) / 2)
cohens_d = (g2.mean() - g1.mean()) / pooled_std
print(f'p-value: {p:.4f}')
print(f'Cohen\'s d: {cohens_d:.3f}')
if cohens_d < 0.2: print('Effect: negligible')
elif cohens_d < 0.5: print('Effect: small')
elif cohens_d < 0.8: print('Effect: medium')
else: print('Effect: large')Pressupostos do teste t
O teste t independente pressupõe: (1) independência — as observações dentro de cada grupo são independentes umas das outras; (2) normalidade — os dados de cada grupo são aproximadamente normais (robustos para n > 30 por meio do CLT); (3) para o teste t de Student (equal_var=True), variâncias iguais. O teste t de Welch (equal_var=False) flexibiliza o terceiro pressuposto e é preferível. Quando a normalidade é seriamente violada em amostras pequenas (< 30), use o teste U de Mann-Whitney.
import numpy as np
from scipy import stats
np.random.seed(0)
g1 = np.random.normal(10, 2, 30)
g2 = np.random.normal(11, 5, 30) # Very different variance!
# Levene test for equal variances
stat_l, p_l = stats.levene(g1, g2)
print(f'Levene test p: {p_l:.4f}')
if p_l < 0.05:
print('Unequal variances -> use Welch\'s (equal_var=False)')
stat, p = stats.ttest_ind(g1, g2, equal_var=False)
else:
print('Equal variances OK -> Student\'s t-test')
stat, p = stats.ttest_ind(g1, g2, equal_var=True)
print(f'Result: t={stat:.3f}, p={p:.4f}')Testes t em séries do Pandas
Na prática, os dados que deseja testar ficam em uma coluna de um DataFrame do Pandas. É possível passar diretamente uma série do Pandas para funções de scipy.stats — elas funcionam perfeitamente tanto com séries quanto com matrizes do NumPy. Um fluxo de trabalho comum é filtrar o DataFrame para obter a série de cada grupo, executar o teste t e armazenar os resultados em um DataFrame de resumo. Esse padrão pode ser ampliado para testar muitos pares de colunas ou grupos em um laço.
import pandas as pd
import numpy as np
from scipy import stats
np.random.seed(0)
df = pd.DataFrame({
'group': ['A']*60 + ['B']*60,
'revenue': np.concatenate([
np.random.normal(100, 20, 60),
np.random.normal(110, 22, 60)
])
})
grp_a = df.loc[df['group'] == 'A', 'revenue']
grp_b = df.loc[df['group'] == 'B', 'revenue']
stat, p = stats.ttest_ind(grp_a, grp_b, equal_var=False)
print(f'A mean: {grp_a.mean():.2f}, B mean: {grp_b.mean():.2f}')
print(f'p-value: {p:.4f}')Problema das comparações múltiplas
Executar muitos testes t simultaneamente aumenta a probabilidade de um falso positivo. Se executar 20 testes t com α=0,05, espera-se 1 falso positivo por acaso. Esse é o problema das comparações múltiplas. Aplique a correção de Bonferroni: divida α pelo número de testes (p_threshold = 0.05 / n_tests). Para obter mais poder com menos conservadorismo, use a correção da Taxa de Falsas Descobertas de Benjamini-Hochberg (FDR), disponível em statsmodels. Corrija sempre as comparações múltiplas em testes A/B com muitas métricas.
import numpy as np
from scipy import stats
np.random.seed(0)
n_tests = 10
results = []
for i in range(n_tests):
g1 = np.random.normal(0, 1, 50)
g2 = np.random.normal(0.1, 1, 50) # Tiny true effect
_, p = stats.ttest_ind(g1, g2)
results.append(p)
print('p-values:', [round(p, 3) for p in results])
bonferroni_thresh = 0.05 / n_tests
print(f'Bonferroni threshold: {bonferroni_thresh}')
print('Significant after Bonferroni:', sum(p < bonferroni_thresh for p in results))Verificação rápida
Teste sua compreensão dos conceitos de Análise de Dados desta lição.
Recapitulação da lição
Nesta lição, você aprendeu que ttest_1samp testa a média de uma amostra em relação a um valor de referência, ttest_ind (o teste de Welch com equal_var=False) compara dois grupos independentes e ttest_rel trata de medições pareadas. Relate sempre o d de Cohen junto com o valor de p para distinguir a significância estatística da prática. Em seguida, testaremos relações entre variáveis categóricas com o teste do qui-quadrado.
Aprenda Python com um tutor de IA — grátis
Escreva e execute código real no seu navegador, obtenha ajuda instantânea de um tutor de IA 24/7 e continue de onde parou na web ou no app.
- Cursos
- 30
- Aulas
- 120
Perguntas Frequentes
A aula “Testes t para comparar médias” é grátis?
Sim — o texto completo de “Testes t para comparar médias” é grátis para ler aqui na web. Para praticá-la interativamente (um editor de código integrado e um tutor de IA 24/7) e desbloquear o restante do curso de Pandas & NumPy Academy, atualize para CoddyKit PRO. O curso de Pandas & NumPy Academy inclui 4 aulas no total.
O que vou aprender em “Testes t para comparar médias”?
Execute testes t de uma amostra, de duas amostras independentes e pareados com scipy.stats e interprete os intervalos de confiança. Você pratica Pandas & NumPy Academy com código prático que executa diretamente no navegador, e um tutor de IA 24/7 responde suas dúvidas enquanto trabalha na aula.
Preciso ter experiência prévia para começar Pandas & NumPy Academy?
Nenhuma experiência prévia é necessária. Pandas & NumPy Academy no CoddyKit é estruturado para alunos iniciantes até avançados, então você pode começar aqui ou desde o início e aprender no seu ritmo. Esta é a aula 2 de 4.
Quanto tempo leva a aula “Testes t para comparar médias”?
A maioria das aulas CoddyKit leva cerca de 5–10 minutos. Cada uma é compacta e interativa, então você faz progresso constante e retoma exatamente de onde parou entre web e app.
Posso escrever e executar código nesta aula de Pandas & NumPy Academy?
Sim. Cada aula de Pandas & NumPy Academy inclui um editor de código integrado, então você escreve e executa código real direto no navegador e recebe feedback de IA instantaneamente — nenhuma configuração local necessária.
Todas as aulas deste curso
- Estatísticas descritivas e teste de normalidade
- Testes t para comparar médias
- Teste qui-quadrado de independência
- ANOVA e testes pós-hoc