📖 Glossário - Estatística Aplicada

A

Alfa (α): Nível de significância, probabilidade de rejeitar H₀ quando é verdadeira (geralmente 0.05).

ANOVA (Analysis of Variance): Teste para comparar médias de três ou mais grupos.

Assimetria (Skewness): Medida de assimetria da distribuição.

Amostra: Subconjunto de população usado para inferência.

B

Beta (β): Probabilidade de não rejeitar H₀ quando é falsa (erro tipo II).

Boxplot: Gráfico que mostra quartis, mediana e outliers.

C

Causalidade: Relação onde uma variável causa mudança em outra.

Chi-quadrado (χ²): Teste para verificar independência entre variáveis categóricas.

Coeficiente de Correlação (r): Medida de força e direção da relação linear (-1 a +1).

Coeficiente de Determinação (R²): Proporção da variância explicada pelo modelo (0 a 1).

Correlação: Medida de associação entre duas variáveis.

Covariância: Medida de variação conjunta de duas variáveis.

Curtose: Medida de achatamento da distribuição.

D

Dados Categóricos: Dados em categorias (nominal/ordinal).

Dados Quantitativos: Dados numéricos (discretos/contínuos).

Desvio Padrão (σ ou s): Medida de dispersão dos dados em torno da média.

Distribuição: Padrão de como valores de variável são espalhados.

Distribuição Normal: Distribuição simétrica em forma de sino.

E

Erro Padrão: Desvio padrão da distribuição amostral.

Erro Tipo I: Rejeitar H₀ quando é verdadeira (falso positivo).

Erro Tipo II: Não rejeitar H₀ quando é falsa (falso negativo).

Estatística Descritiva: Resumo e descrição de dados.

Estatística Inferencial: Conclusões sobre população a partir de amostra.

Estimador: Fórmula usada para estimar parâmetro populacional.

F

F de Fisher: Estatística usada em ANOVA para comparar variâncias.

G

Graus de Liberdade: Número de valores livres para variar em cálculo estatístico.

H

Histograma: Gráfico de frequência de dados contínuos.

Hipótese Alternativa (H₁): Afirmação que queremos provar.

Hipótese Nula (H₀): Afirmação de que não há efeito/diferença.

I

IC (Intervalo de Confiança): Faixa de valores prováveis para parâmetro populacional.

IQR (Interquartile Range): Diferença entre Q3 e Q1, medida de dispersão.

K

Kolmogorov-Smirnov: Teste de normalidade de distribuição.

Kurtosis: Ver Curtose.

L

Linearidade: Relação proporcional entre variáveis.

M

Mann-Whitney: Teste não-paramétrico para comparar dois grupos independentes.

Máximo: Maior valor em conjunto de dados.

Média (x̄ ou μ): Soma dos valores dividida pelo número de observações.

Mediana: Valor central quando dados estão ordenados.

Mínimo: Menor valor em conjunto de dados.

Moda: Valor mais frequente em conjunto de dados.

N

Normalidade: Propriedade de dados seguirem distribuição normal.

Nível de Confiança: Probabilidade de IC conter parâmetro verdadeiro (ex: 95%).

O

Outlier: Valor extremo que destoa do padrão.

P

p-valor: Probabilidade de obter resultado observado se H₀ for verdadeira.

Parâmetro: Característica numérica de população (μ, σ).

Percentil: Valor abaixo do qual certa porcentagem de dados cai.

Poder do Teste (1-β): Probabilidade de rejeitar H₀ quando é falsa.

População: Conjunto completo de elementos de interesse.

Q

Q1 (Primeiro Quartil): Valor que deixa 25% dos dados abaixo.

Q2 (Segundo Quartil): Mediana (50%).

Q3 (Terceiro Quartil): Valor que deixa 75% dos dados abaixo.

R

Regressão: Técnica para modelar relação entre variáveis.

Regressão Linear: Modelo de relação linear entre variáveis.

Regressão Múltipla: Regressão com múltiplas variáveis explicativas.

Resíduo: Diferença entre valor observado e previsto.

R de Pearson: Coeficiente de correlação linear.

S

Shapiro-Wilk: Teste de normalidade sensível.

Significância Estatística: Resultado improvável de ocorrer por acaso (p < α).

Spearman (ρ): Coeficiente de correlação de postos (não-paramétrico).

T

Teste Bicaudal: Teste que considera desvios em ambas direções.

Teste de Hipótese: Procedimento para decidir entre H₀ e H₁.

Teste Paramétrico: Teste que assume distribuição específica dos dados.

Teste t de Student: Teste para comparar médias.

Teste Unicaudal: Teste que considera desvio em uma direção.

V

Valor-p: Ver p-valor.

Variância (σ² ou s²): Média dos desvios quadráticos em relação à média.

Variável Dependente (Y): Variável que queremos explicar/prever.

Variável Independente (X): Variável explicativa/preditora.

W

Wilcoxon: Teste não-paramétrico para dados pareados.

Z

z-score: Número de desvios padrão que valor está da média.

Fórmulas Essenciais

Estatística Descritiva

Média: x̄ = Σx / n

Variância:  = Σ(x - x̄)² / (n-1)

Desvio Padrão: s = 

Coeficiente de Variação: CV = (s / x̄) × 100%

Correlação e Regressão

Correlação de Pearson: r = Σ[(x - x̄)(y - ȳ)] / √[Σ(x - x̄)²Σ(y - ȳ)²]

Regressão Linear: y = a + bx
    b = Σ[(x - x̄)(y - ȳ)] / Σ(x - x̄)²
    a = ȳ - bx̄

R²: R² = 1 - (SSres / SStot)

Testes de Hipótese

Teste t: t = (x̄ - μ₀) / (s / √n)

Intervalo de Confiança (95%): x̄ ± t₀.₀₂₅ × (s / √n)

Tamanho de Efeito (Cohen's d): d = (x̄₁ - x̄₂) / s_pooled

Exemplos Práticos

Estatística Descritiva Completa

import pandas as pd
import numpy as np
from scipy import stats

# Dados de temperatura
temperaturas = [22.5, 23.1, 21.8, 24.2, 22.9, 23.5, 22.1, 23.8, 22.6, 23.3]

# Estatísticas básicas
print("Média:", np.mean(temperaturas))
print("Mediana:", np.median(temperaturas))
print("Moda:", stats.mode(temperaturas))
print("Desvio Padrão:", np.std(temperaturas, ddof=1))
print("Variância:", np.var(temperaturas, ddof=1))
print("Mínimo:", np.min(temperaturas))
print("Máximo:", np.max(temperaturas))
print("Amplitude:", np.max(temperaturas) - np.min(temperaturas))

# Quartis
q1 = np.percentile(temperaturas, 25)
q2 = np.percentile(temperaturas, 50)  # Mediana
q3 = np.percentile(temperaturas, 75)
iqr = q3 - q1

print(f"Q1: {q1}, Q2: {q2}, Q3: {q3}, IQR: {iqr}")

# Teste de normalidade
estatistica, p_valor = stats.shapiro(temperaturas)
print(f"Shapiro-Wilk: p-valor = {p_valor:.4f}")
if p_valor > 0.05:
    print("Dados são normalmente distribuídos")

Teste de Hipótese (Teste t)

import scipy.stats as stats

# Dados: temperatura antes e depois de intervenção
antes = [22.5, 23.1, 21.8, 24.2, 22.9]
depois = [20.1, 19.8, 21.2, 20.5, 19.9]

# Teste t pareado
t_stat, p_valor = stats.ttest_rel(antes, depois)

print(f"Estatística t: {t_stat:.3f}")
print(f"p-valor: {p_valor:.4f}")

alpha = 0.05
if p_valor < alpha:
    print("Há diferença significativa (rejeitar H₀)")
else:
    print("Não há diferença significativa (não rejeitar H₀)")

# Tamanho de efeito
d = np.mean(np.array(antes) - np.array(depois)) / np.std(np.array(antes) - np.array(depois), ddof=1)
print(f"Cohen's d: {d:.3f}")

Correlação e Regressão

import matplotlib.pyplot as plt
from scipy.stats import pearsonr, spearmanr

# Dados
temperatura = [20, 22, 24, 26, 28, 30, 32]
abundancia = [45, 52, 58, 62, 55, 48, 42]

# Correlação de Pearson
r_pearson, p_pearson = pearsonr(temperatura, abundancia)
print(f"Correlação de Pearson: r = {r_pearson:.3f}, p = {p_pearson:.4f}")

# Correlação de Spearman
r_spearman, p_spearman = spearmanr(temperatura, abundancia)
print(f"Correlação de Spearman: ρ = {r_spearman:.3f}, p = {p_spearman:.4f}")

# Regressão linear
from scipy.stats import linregress
slope, intercept, r_value, p_value, std_err = linregress(temperatura, abundancia)

print(f"Equação: y = {intercept:.2f} + {slope:.2f}x")
print(f"R² = {r_value**2:.3f}")

# Plotar
plt.figure(figsize=(10, 6))
plt.scatter(temperatura, abundancia, s=100, alpha=0.6, label='Dados')
plt.plot(temperatura, intercept + slope*np.array(temperatura), 'r-', label='Regressão')
plt.xlabel('Temperatura (°C)')
plt.ylabel('Abundância')
plt.title(f'Correlação: r = {r_pearson:.3f}')
plt.legend()
plt.grid(True, alpha=0.3)
plt.savefig('regressao.png', dpi=300, bbox_inches='tight')

ANOVA (Comparação de 3+ grupos)

from scipy.stats import f_oneway

# Dados de 3 praias
praia1 = [22.5, 23.1, 22.8, 23.2]
praia2 = [25.1, 24.8, 25.3, 25.0]
praia3 = [21.2, 20.9, 21.5, 21.1]

# ANOVA
F_stat, p_valor = f_oneway(praia1, praia2, praia3)

print(f"Estatística F: {F_stat:.3f}")
print(f"p-valor: {p_valor:.4f}")

if p_valor < 0.05:
    print("Há diferença significativa entre as praias")
else:
    print("Não há diferença significativa entre as praias")

Guia de Escolha de Teste

Situação Teste Recomendado
Comparar 2 grupos independentes (dados normais) Teste t independente
Comparar 2 grupos pareados (dados normais) Teste t pareado
Comparar 2 grupos (dados não-normais) Mann-Whitney
Comparar 3+ grupos (dados normais) ANOVA
Comparar 3+ grupos (dados não-normais) Kruskal-Wallis
Correlação linear Pearson
Correlação não-linear Spearman
Testar normalidade Shapiro-Wilk
Variáveis categóricas Chi-quadrado

💡 Dica: Sempre verifique as premissas do teste antes de aplicá-lo!

📊 Estatística Descritiva para Dados Biológicos

🎯 Objetivo da Lição

Aprender a calcular e interpretar estatísticas descritivas essenciais para análise de dados de pesquisa: médias, medianas, desvio padrão, quartis e muito mais.

Por que é importante: - Resumir grandes conjuntos de dados - Identificar padrões e anomalias - Tomar decisões baseadas em evidências - Comunicar resultados de forma clara


📐 Medidas de Tendência Central

Média Aritmética

Definição: Soma de todos os valores dividido pela quantidade.

import numpy as np

# Biomassas coletadas (gramas)
biomassas = [245.3, 180.7, 310.2, 198.5, 220.4, 302.1, 195.8, 275.4]

# Calcular média
media = np.mean(biomassas)
print(f"Média: {media:.2f}g")  # 241.05g

# Ou manualmente:
media_manual = sum(biomassas) / len(biomassas)

Quando usar: Dados simétricos sem outliers extremos.


Mediana

Definição: Valor central quando os dados estão ordenados.

# Calcular mediana
mediana = np.median(biomassas)
print(f"Mediana: {mediana:.2f}g")  # 233.75g

# Manualmente:
biomassas_ordenadas = sorted(biomassas)
meio = len(biomassas_ordenadas) // 2
if len(biomassas_ordenadas) % 2 == 0:
    mediana_manual = (biomassas_ordenadas[meio-1] + biomassas_ordenadas[meio]) / 2
else:
    mediana_manual = biomassas_ordenadas[meio]

Quando usar: Dados com outliers ou distribuição assimétrica.


Moda

Definição: Valor que aparece com maior frequência.

from scipy import stats

especies = ['Ulva lactuca', 'Gracilaria', 'Ulva lactuca', 'Sargassum', 
            'Ulva lactuca', 'Gracilaria', 'Ulva lactuca']

moda = stats.mode(especies, keepdims=True)
print(f"Espécie mais comum: {moda.mode[0]}")  # Ulva lactuca
print(f"Frequência: {moda.count[0]} vezes")   # 4 vezes

📏 Medidas de Dispersão

Variância e Desvio Padrão

Variância: Média dos quadrados das diferenças em relação à média.
Desvio Padrão: Raiz quadrada da variância (mesma unidade dos dados).

# Temperaturas registradas (°C)
temperaturas = [24.5, 26.1, 22.3, 21.5, 19.8, 18.2, 17.5, 18.0, 19.5, 21.0]

# Variância
variancia = np.var(temperaturas, ddof=1)  # ddof=1 para amostra
print(f"Variância: {variancia:.2f} °C²")

# Desvio padrão
desvio_padrao = np.std(temperaturas, ddof=1)
print(f"Desvio padrão: {desvio_padrao:.2f} °C")

# Interpretação
media_temp = np.mean(temperaturas)
print(f"\nTemperatura: {media_temp:.1f} ± {desvio_padrao:.1f} °C")

Interpretação: - Desvio padrão baixo → Dados concentrados perto da média - Desvio padrão alto → Dados dispersos


Coeficiente de Variação

Definição: Desvio padrão relativo à média (em %).

cv = (desvio_padrao / media_temp) * 100
print(f"Coeficiente de Variação: {cv:.2f}%")

# Interpretação:
if cv < 10:
    print("Variabilidade: BAIXA")
elif cv < 30:
    print("Variabilidade: MODERADA")
else:
    print("Variabilidade: ALTA")

Amplitude e Amplitude Interquartil

# Amplitude total (range)
amplitude = max(temperaturas) - min(temperaturas)
print(f"Amplitude: {amplitude:.1f} °C")

# Quartis
q1 = np.percentile(temperaturas, 25)  # 1º quartil (25%)
q2 = np.percentile(temperaturas, 50)  # 2º quartil (mediana)
q3 = np.percentile(temperaturas, 75)  # 3º quartil (75%)

# Amplitude interquartil (IQR)
iqr = q3 - q1
print(f"\nQ1 (25%): {q1:.1f} °C")
print(f"Q2 (50%): {q2:.1f} °C")
print(f"Q3 (75%): {q3:.1f} °C")
print(f"IQR: {iqr:.1f} °C")

IQR: Contém os 50% centrais dos dados (menos sensível a outliers).


📊 Exemplo Completo: Análise de Coletas

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from scipy import stats

# Dataset de coletas
dados = {
    'praia': ['Ingleses', 'Ingleses', 'Barra', 'Barra', 'Armação', 
              'Armação', 'Garopaba', 'Garopaba', 'Laguna', 'Laguna'],
    'especie': ['Ulva', 'Gracilaria', 'Ulva', 'Sargassum', 'Ulva', 
                'Gracilaria', 'Ulva', 'Laminaria', 'Ulva', 'Gracilaria'],
    'biomassa_g': [245.3, 180.7, 302.1, 310.2, 275.4, 195.8, 310.8, 425.8, 295.7, 205.6],
    'temperatura_c': [24.5, 24.5, 22.3, 23.8, 21.5, 21.5, 19.8, 21.0, 18.0, 18.0],
    'profundidade_m': [3.2, 5.1, 3.5, 4.5, 3.8, 5.0, 3.6, 10.5, 3.7, 5.4]
}

df = pd.DataFrame(dados)

# ====================
# ESTATÍSTICAS GERAIS
# ====================

print("="*60)
print("📊 ESTATÍSTICAS DESCRITIVAS - BIOMASSA")
print("="*60)

biomassas = df['biomassa_g']

print(f"\n📏 Tendência Central:")
print(f"   Média: {biomassas.mean():.2f}g")
print(f"   Mediana: {biomassas.median():.2f}g")

print(f"\n📐 Dispersão:")
print(f"   Desvio Padrão: {biomassas.std():.2f}g")
print(f"   Variância: {biomassas.var():.2f}g²")
print(f"   CV: {(biomassas.std() / biomassas.mean() * 100):.2f}%")

print(f"\n📊 Valores Extremos:")
print(f"   Mínimo: {biomassas.min():.2f}g")
print(f"   Máximo: {biomassas.max():.2f}g")
print(f"   Amplitude: {biomassas.max() - biomassas.min():.2f}g")

print(f"\n🎯 Quartis:")
print(f"   Q1 (25%): {biomassas.quantile(0.25):.2f}g")
print(f"   Q2 (50%): {biomassas.quantile(0.50):.2f}g")
print(f"   Q3 (75%): {biomassas.quantile(0.75):.2f}g")
print(f"   IQR: {biomassas.quantile(0.75) - biomassas.quantile(0.25):.2f}g")

# ====================
# POR ESPÉCIE
# ====================

print("\n" + "="*60)
print("🌿 ESTATÍSTICAS POR ESPÉCIE")
print("="*60)

for especie in df['especie'].unique():
    dados_especie = df[df['especie'] == especie]['biomassa_g']

    print(f"\n📌 {especie}")
    print(f"   n = {len(dados_especie)}")
    print(f"   Média: {dados_especie.mean():.2f}g ± {dados_especie.std():.2f}g")
    print(f"   Mediana: {dados_especie.median():.2f}g")
    print(f"   Range: [{dados_especie.min():.2f}, {dados_especie.max():.2f}]g")

# ====================
# VISUALIZAÇÕES
# ====================

fig, axes = plt.subplots(2, 2, figsize=(12, 10))
fig.suptitle('📊 Análise Estatística de Coletas', fontsize=16, fontweight='bold')

# 1. Histograma
ax1 = axes[0, 0]
ax1.hist(biomassas, bins=6, edgecolor='black', alpha=0.7, color='skyblue')
ax1.axvline(biomassas.mean(), color='red', linestyle='--', linewidth=2, label=f'Média: {biomassas.mean():.1f}g')
ax1.axvline(biomassas.median(), color='green', linestyle='--', linewidth=2, label=f'Mediana: {biomassas.median():.1f}g')
ax1.set_xlabel('Biomassa (g)')
ax1.set_ylabel('Frequência')
ax1.set_title('Histograma de Biomassa')
ax1.legend()
ax1.grid(True, alpha=0.3)

# 2. Boxplot
ax2 = axes[0, 1]
ax2.boxplot(biomassas, vert=True)
ax2.set_ylabel('Biomassa (g)')
ax2.set_title('Boxplot de Biomassa')
ax2.grid(True, alpha=0.3)

# 3. Boxplot por espécie
ax3 = axes[1, 0]
especies_ordenadas = df.groupby('especie')['biomassa_g'].median().sort_values().index
df_plot = df.set_index('especie').loc[especies_ordenadas]
df_plot.boxplot(column='biomassa_g', by='especie', ax=ax3)
ax3.set_xlabel('Espécie')
ax3.set_ylabel('Biomassa (g)')
ax3.set_title('Biomassa por Espécie')
plt.sca(ax3)
plt.xticks(rotation=45, ha='right')

# 4. Scatter com tendência
ax4 = axes[1, 1]
ax4.scatter(df['temperatura_c'], df['biomassa_g'], s=100, alpha=0.6, edgecolors='black')
ax4.set_xlabel('Temperatura (°C)')
ax4.set_ylabel('Biomassa (g)')
ax4.set_title('Biomassa vs Temperatura')
ax4.grid(True, alpha=0.3)

# Linha de tendência
z = np.polyfit(df['temperatura_c'], df['biomassa_g'], 1)
p = np.poly1d(z)
ax4.plot(df['temperatura_c'], p(df['temperatura_c']), 
         "r--", alpha=0.8, linewidth=2, label='Tendência')
ax4.legend()

plt.tight_layout()
plt.savefig('estatisticas_descritivas.png', dpi=300)
print("\n✅ Gráfico salvo: estatisticas_descritivas.png")
plt.show()

print("\n" + "="*60)
print("✅ ANÁLISE CONCLUÍDA!")
print("="*60)

📈 Resumo dos 5 Números

Five-number summary: Resumo completo da distribuição.

def resumo_cinco_numeros(dados):
    """Calcula e exibe o resumo de 5 números"""
    minimo = np.min(dados)
    q1 = np.percentile(dados, 25)
    mediana = np.median(dados)
    q3 = np.percentile(dados, 75)
    maximo = np.max(dados)

    print("\n📊 RESUMO DOS 5 NÚMEROS:")
    print(f"   Mínimo:   {minimo:.2f}")
    print(f"   Q1 (25%): {q1:.2f}")
    print(f"   Mediana:  {mediana:.2f}")
    print(f"   Q3 (75%): {q3:.2f}")
    print(f"   Máximo:   {maximo:.2f}")

    return minimo, q1, mediana, q3, maximo

resumo_cinco_numeros(biomassas)

🔍 Identificação de Outliers

Método IQR: Valores fora de 1.5 × IQR são considerados outliers.

def identificar_outliers(dados):
    """Identifica outliers usando método IQR"""
    q1 = np.percentile(dados, 25)
    q3 = np.percentile(dados, 75)
    iqr = q3 - q1

    # Limites
    limite_inferior = q1 - 1.5 * iqr
    limite_superior = q3 + 1.5 * iqr

    # Identificar outliers
    outliers = [x for x in dados if x < limite_inferior or x > limite_superior]

    print(f"\n🔍 DETECÇÃO DE OUTLIERS:")
    print(f"   Limite inferior: {limite_inferior:.2f}")
    print(f"   Limite superior: {limite_superior:.2f}")

    if outliers:
        print(f"   ⚠️ {len(outliers)} outlier(s) detectado(s): {outliers}")
    else:
        print(f"   ✅ Nenhum outlier detectado")

    return outliers

identificar_outliers(df['biomassa_g'])

🎓 Checklist desta Lição

  • [ ] Calculei média, mediana e moda
  • [ ] Entendi desvio padrão e variância
  • [ ] Criei boxplots para visualizar distribuição
  • [ ] Identifiquei outliers usando IQR
  • [ ] Comparei estatísticas entre grupos

➡️ Próxima Lição

  • 02-Testes-Hipotese.html (Testes estatísticos: t-test, ANOVA, etc.)

Você domina estatística descritiva! 📊✨

🧪 Testes de Hipótese para Dados Biológicos

🎯 Objetivo da Lição

Aprender a realizar testes estatísticos para comparar grupos e testar hipóteses científicas usando Python.

O que faremos: - Teste t (Student's t-test) - ANOVA (Analysis of Variance) - Testes não-paramétricos - Interpretar p-valores - Tomar decisões estatísticas


🔬 Conceitos Fundamentais

Hipótese Nula (H₀) vs Alternativa (H₁)

H₀: Não  diferença entre os grupos
H₁:  diferença entre os grupos

P-valor

Definição: Probabilidade de obter os resultados observados se H₀ for verdadeira.

if p_valor < 0.05:
    print("✅ Rejeitamos H₀ (diferença significativa)")
else:
    print("❌ Não rejeitamos H₀ (sem diferença significativa)")

Níveis de significância comuns: - α = 0.05 (5%) → padrão - α = 0.01 (1%) → mais rigoroso - α = 0.10 (10%) → exploratório


📊 Teste t de Student

Teste t para Uma Amostra

Objetivo: Comparar média da amostra com valor de referência.

Exemplo: Biomassa média é diferente de 250g?

from scipy import stats
import numpy as np

# Dados de biomassa (g)
biomassas = [245.3, 180.7, 310.2, 198.5, 220.4, 302.1, 195.8, 275.4]

# Valor de referência (hipotético)
valor_referencia = 250

# Realizar teste t para uma amostra
t_stat, p_valor = stats.ttest_1samp(biomassas, valor_referencia)

print("="*60)
print("🧪 TESTE T PARA UMA AMOSTRA")
print("="*60)
print(f"\nH₀: μ = {valor_referencia}g")
print(f"H₁: μ ≠ {valor_referencia}g")
print(f"\nMédia observada: {np.mean(biomassas):.2f}g")
print(f"Estatística t: {t_stat:.4f}")
print(f"P-valor: {p_valor:.4f}")

if p_valor < 0.05:
    print("\n✅ Resultado: SIGNIFICATIVO (p < 0.05)")
    print("   Rejeitamos H₀: A média é diferente de 250g")
else:
    print("\n❌ Resultado: NÃO SIGNIFICATIVO (p ≥ 0.05)")
    print("   Não rejeitamos H₀: A média pode ser 250g")

Teste t para Amostras Independentes

Objetivo: Comparar médias de dois grupos diferentes.

Exemplo: Biomassa de Ulva vs Gracilaria é diferente?

import pandas as pd

# Dados de duas espécies
dados = {
    'especie': ['Ulva', 'Ulva', 'Ulva', 'Ulva', 'Ulva',
                'Gracilaria', 'Gracilaria', 'Gracilaria', 'Gracilaria'],
    'biomassa_g': [245.3, 302.1, 275.4, 310.8, 295.7,
                   180.7, 195.8, 205.6, 220.4]
}

df = pd.DataFrame(dados)

# Separar grupos
ulva = df[df['especie'] == 'Ulva']['biomassa_g']
gracilaria = df[df['especie'] == 'Gracilaria']['biomassa_g']

# Teste t independente
t_stat, p_valor = stats.ttest_ind(ulva, gracilaria)

print("\n" + "="*60)
print("🧪 TESTE T PARA AMOSTRAS INDEPENDENTES")
print("="*60)
print(f"\nH₀: μ₁ = μ₂ (médias iguais)")
print(f"H₁: μ₁ ≠ μ₂ (médias diferentes)")

print(f"\n📊 Estatísticas descritivas:")
print(f"   Ulva:       n={len(ulva)}, média={ulva.mean():.2f}g ± {ulva.std():.2f}g")
print(f"   Gracilaria: n={len(gracilaria)}, média={gracilaria.mean():.2f}g ± {gracilaria.std():.2f}g")

print(f"\n🔬 Resultado do teste:")
print(f"   Estatística t: {t_stat:.4f}")
print(f"   P-valor: {p_valor:.4f}")

if p_valor < 0.05:
    print("\n✅ Conclusão: Há diferença significativa entre as espécies (p < 0.05)")
    diferenca = ulva.mean() - gracilaria.mean()
    print(f"   Ulva tem {abs(diferenca):.2f}g {'a mais' if diferenca > 0 else 'a menos'} que Gracilaria")
else:
    print("\n❌ Conclusão: Não há diferença significativa (p ≥ 0.05)")

Teste t Pareado

Objetivo: Comparar médias de duas medições no mesmo indivíduo/local.

Exemplo: Biomassa antes vs depois de tratamento.

# Biomassa antes e depois de experimento (mesmos locais)
antes = [245.3, 180.7, 310.2, 198.5, 220.4]
depois = [280.1, 195.3, 335.8, 210.2, 245.7]

# Teste t pareado
t_stat, p_valor = stats.ttest_rel(antes, depois)

print("\n" + "="*60)
print("🧪 TESTE T PAREADO")
print("="*60)
print(f"\nH₀: μ_diferença = 0 (sem mudança)")
print(f"H₁: μ_diferença ≠ 0 (houve mudança)")

diferencas = [d - a for d, a in zip(depois, antes)]
print(f"\n📊 Diferenças: {[f'{d:.1f}' for d in diferencas]}")
print(f"   Média das diferenças: {np.mean(diferencas):.2f}g")

print(f"\n🔬 Resultado do teste:")
print(f"   Estatística t: {t_stat:.4f}")
print(f"   P-valor: {p_valor:.4f}")

if p_valor < 0.05:
    print("\n✅ Conclusão: Houve mudança significativa (p < 0.05)")
else:
    print("\n❌ Conclusão: Não houve mudança significativa (p ≥ 0.05)")

📊 ANOVA (Analysis of Variance)

Objetivo: Comparar médias de 3 ou mais grupos.

Exemplo: Biomassa difere entre 4 praias?

# Dados de 4 praias
praia1 = [245.3, 302.1, 275.4]  # Ingleses
praia2 = [180.7, 195.8, 205.6]  # Barra
praia3 = [310.2, 340.5, 315.2]  # Armação
praia4 = [198.5, 220.4, 210.8]  # Garopaba

# ANOVA one-way
f_stat, p_valor = stats.f_oneway(praia1, praia2, praia3, praia4)

print("\n" + "="*60)
print("🧪 ANOVA (ONE-WAY)")
print("="*60)
print(f"\nH₀: μ₁ = μ₂ = μ₃ = μ₄ (todas as médias iguais)")
print(f"H₁: Pelo menos uma média é diferente")

print(f"\n📊 Estatísticas por praia:")
praias = [praia1, praia2, praia3, praia4]
nomes = ['Ingleses', 'Barra', 'Armação', 'Garopaba']

for nome, dados in zip(nomes, praias):
    print(f"   {nome}: média={np.mean(dados):.2f}g ± {np.std(dados, ddof=1):.2f}g")

print(f"\n🔬 Resultado do ANOVA:")
print(f"   Estatística F: {f_stat:.4f}")
print(f"   P-valor: {p_valor:.4f}")

if p_valor < 0.05:
    print("\n✅ Conclusão: Há diferença significativa entre as praias (p < 0.05)")
    print("   💡 Use teste post-hoc (Tukey) para ver quais praias diferem")
else:
    print("\n❌ Conclusão: Não há diferença significativa (p ≥ 0.05)")

Teste Post-Hoc (Tukey HSD)

from scipy.stats import tukey_hsd

# Após ANOVA significativo, identificar diferenças
result = tukey_hsd(praia1, praia2, praia3, praia4)

print("\n" + "="*60)
print("📊 TESTE POST-HOC (TUKEY HSD)")
print("="*60)
print("\nComparações pareadas:")
print(result)

🔄 Testes Não-Paramétricos

Quando usar?

  • Dados não seguem distribuição normal
  • Amostras pequenas (n < 30)
  • Dados ordinais (rankings)
  • Presença de outliers

Mann-Whitney U (alternativa ao teste t)

# Comparar dois grupos (não-paramétrico)
grupo1 = [245, 180, 310, 198, 220]
grupo2 = [302, 195, 275, 310, 295]

u_stat, p_valor = stats.mannwhitneyu(grupo1, grupo2, alternative='two-sided')

print("\n" + "="*60)
print("🧪 MANN-WHITNEY U TEST")
print("="*60)
print(f"Estatística U: {u_stat:.4f}")
print(f"P-valor: {p_valor:.4f}")

if p_valor < 0.05:
    print("✅ Diferença significativa (p < 0.05)")
else:
    print("❌ Sem diferença significativa (p ≥ 0.05)")

Kruskal-Wallis (alternativa ao ANOVA)

# Comparar 3+ grupos (não-paramétrico)
h_stat, p_valor = stats.kruskal(praia1, praia2, praia3, praia4)

print("\n" + "="*60)
print("🧪 KRUSKAL-WALLIS TEST")
print("="*60)
print(f"Estatística H: {h_stat:.4f}")
print(f"P-valor: {p_valor:.4f}")

📈 Exemplo Completo: Análise Comparativa

import numpy as np
import pandas as pd
from scipy import stats
import matplotlib.pyplot as plt

# Dataset completo
dados = {
    'praia': ['Ingleses']*5 + ['Barra']*5 + ['Armação']*5,
    'biomassa_g': [245.3, 302.1, 275.4, 310.8, 295.7,  # Ingleses
                   180.7, 195.8, 205.6, 220.4, 198.5,  # Barra
                   310.2, 340.5, 315.2, 325.8, 330.1]  # Armação
}

df = pd.DataFrame(dados)

print("="*70)
print("🔬 ANÁLISE COMPARATIVA COMPLETA")
print("="*70)

# ====================
# 1. ESTATÍSTICAS DESCRITIVAS
# ====================

print("\n📊 ESTATÍSTICAS POR PRAIA:")
print("-"*70)

for praia in df['praia'].unique():
    dados_praia = df[df['praia'] == praia]['biomassa_g']
    print(f"\n{praia}:")
    print(f"   n = {len(dados_praia)}")
    print(f"   Média = {dados_praia.mean():.2f}g ± {dados_praia.std():.2f}g")
    print(f"   Mediana = {dados_praia.median():.2f}g")
    print(f"   Range = [{dados_praia.min():.2f}, {dados_praia.max():.2f}]g")

# ====================
# 2. TESTE DE NORMALIDADE
# ====================

print("\n" + "="*70)
print("🔍 TESTE DE NORMALIDADE (SHAPIRO-WILK)")
print("="*70)

for praia in df['praia'].unique():
    dados_praia = df[df['praia'] == praia]['biomassa_g']
    stat, p_valor = stats.shapiro(dados_praia)

    normal = "SIM ✅" if p_valor > 0.05 else "NÃO ❌"
    print(f"\n{praia}: p={p_valor:.4f} → Distribução normal? {normal}")

# ====================
# 3. ANOVA
# ====================

print("\n" + "="*70)
print("🧪 ANOVA ONE-WAY")
print("="*70)

ingleses = df[df['praia'] == 'Ingleses']['biomassa_g']
barra = df[df['praia'] == 'Barra']['biomassa_g']
armacao = df[df['praia'] == 'Armação']['biomassa_g']

f_stat, p_valor = stats.f_oneway(ingleses, barra, armacao)

print(f"\nH₀: μ₁ = μ₂ = μ₃")
print(f"Estatística F: {f_stat:.4f}")
print(f"P-valor: {p_valor:.6f}")

if p_valor < 0.05:
    print("\n✅ RESULTADO: Há diferença significativa entre praias (p < 0.05)")
else:
    print("\n❌ RESULTADO: Não há diferença significativa (p ≥ 0.05)")

# ====================
# 4. COMPARAÇÕES PAREADAS (Post-hoc)
# ====================

if p_valor < 0.05:
    print("\n" + "="*70)
    print("📊 COMPARAÇÕES PAREADAS (TESTE T)")
    print("="*70)

    comparacoes = [
        ('Ingleses', ingleses, 'Barra', barra),
        ('Ingleses', ingleses, 'Armação', armacao),
        ('Barra', barra, 'Armação', armacao)
    ]

    for nome1, dados1, nome2, dados2 in comparacoes:
        t_stat, p = stats.ttest_ind(dados1, dados2)

        # Correção de Bonferroni
        p_corrigido = p * 3  # 3 comparações

        sig = "✅ SIG" if p_corrigido < 0.05 else "❌ NS"
        print(f"\n{nome1} vs {nome2}:")
        print(f"   p-valor: {p:.4f} (corrigido: {p_corrigido:.4f}) {sig}")

# ====================
# 5. VISUALIZAÇÃO
# ====================

fig, axes = plt.subplots(1, 2, figsize=(14, 5))

# Boxplot
ax1 = axes[0]
df.boxplot(column='biomassa_g', by='praia', ax=ax1)
ax1.set_xlabel('Praia', fontweight='bold')
ax1.set_ylabel('Biomassa (g)', fontweight='bold')
ax1.set_title('Distribuição de Biomassa por Praia')
plt.sca(ax1)
plt.xticks(rotation=0)

# Barplot com erro
ax2 = axes[1]
medias = df.groupby('praia')['biomassa_g'].mean()
erros = df.groupby('praia')['biomassa_g'].std()

ax2.bar(range(len(medias)), medias, yerr=erros, 
        capsize=5, alpha=0.7, edgecolor='black', color=['skyblue', 'lightcoral', 'lightgreen'])
ax2.set_xticks(range(len(medias)))
ax2.set_xticklabels(medias.index, rotation=0)
ax2.set_xlabel('Praia', fontweight='bold')
ax2.set_ylabel('Biomassa Média (g)', fontweight='bold')
ax2.set_title('Biomassa Média (± DP)')
ax2.grid(True, alpha=0.3, axis='y')

plt.tight_layout()
plt.savefig('analise_comparativa.png', dpi=300)
print("\n✅ Gráfico salvo: analise_comparativa.png")

plt.show()

print("\n" + "="*70)
print("✅ ANÁLISE CONCLUÍDA!")
print("="*70)

🎓 Checklist desta Lição

  • [ ] Entendi hipótese nula e alternativa
  • [ ] Realizei teste t para comparar 2 grupos
  • [ ] Usei ANOVA para comparar 3+ grupos
  • [ ] Interpretei p-valores corretamente
  • [ ] Apliquei testes não-paramétricos quando necessário

➡️ Próxima Lição

  • 03-Correlacao-Regressao.html (Análise de relações entre variáveis)

Você domina testes de hipótese! 🧪✨

📈 Correlação e Regressão

🎯 Objetivo da Lição

Entender relações entre variáveis e criar modelos simples para previsão usando correlação e regressão.

— Quando duas variáveis variam juntas, há correlação. — Regressão estima como uma variável explica outra.


🔗 Correlação (Pearson)

Mede relação linear entre duas variáveis (−1 a +1).

import numpy as np
import pandas as pd

# Exemplo: biomassa vs temperatura
biomassa = np.array([245.3, 198.5, 302.1, 275.4, 310.8, 285.2, 320.5, 295.7, 260.8, 280.3])
temperatura = np.array([24.5, 26.1, 22.3, 21.5, 19.8, 18.2, 17.5, 18.0, 19.5, 21.0])

# Correlação de Pearson
corr = np.corrcoef(biomassa, temperatura)[0, 1]
print(f"Correlação (Pearson): {corr:.3f}")

Interpretação: - |r| ≥ 0.7 → forte - 0.4–0.7 → moderada - 0.2–0.4 → fraca


📊 Matriz de Correlação

# Dataset de exemplo
import seaborn as sns
import matplotlib.pyplot as plt

dados = {
    'biomassa_g': biomassa,
    'temperatura_c': temperatura,
    'salinidade_psu': [35.0, 34.5, 35.2, 35.3, 35.4, 35.5, 35.6, 35.4, 35.2, 35.0],
    'profundidade_m': [3.2, 3.0, 3.5, 3.8, 3.6, 3.4, 3.9, 3.7, 3.5, 3.8]
}

df = pd.DataFrame(dados)

corr_mtx = df.corr(numeric_only=True)
print(corr_mtx.round(3))

plt.figure(figsize=(6, 5))
sns.heatmap(corr_mtx, annot=True, cmap='Blues', vmin=-1, vmax=1)
plt.title('Matriz de Correlação')
plt.tight_layout()
plt.savefig('matriz_correlacao.png', dpi=300)
plt.show()

📉 Regressão Linear Simples

Modelo: y = a + b·x

from sklearn.linear_model import LinearRegression
from sklearn.metrics import r2_score, mean_squared_error

X = temperatura.reshape(-1, 1)
y = biomassa

modelo = LinearRegression()
modelo.fit(X, y)

# Coeficientes
intercepto = modelo.intercept_
coef = modelo.coef_[0]
print(f"Modelo: biomassa = {intercepto:.2f} + {coef:.2f}·temperatura")

# Avaliação
y_pred = modelo.predict(X)
r2 = r2_score(y, y_pred)
rmse = np.sqrt(mean_squared_error(y, y_pred))
print(f"R²: {r2:.3f} | RMSE: {rmse:.2f}g")

Visualização:

plt.figure(figsize=(7,5))
plt.scatter(temperatura, biomassa, s=90, edgecolors='black', alpha=0.7)
plt.plot(temperatura, y_pred, 'r--', linewidth=2)
plt.xlabel('Temperatura (°C)')
plt.ylabel('Biomassa (g)')
plt.title('Regressão Linear: Biomassa vs Temperatura')
plt.grid(True, alpha=0.3)
plt.tight_layout()
plt.savefig('regressao_simples.png', dpi=300)
plt.show()

📈 Regressão Múltipla

Várias variáveis explicam y.

from sklearn.model_selection import train_test_split

X = df[['temperatura_c', 'salinidade_psu', 'profundidade_m']]
y = df['biomassa_g']

X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

modelo = LinearRegression()
modelo.fit(X_train, y_train)

coeficientes = pd.Series(modelo.coef_, index=X.columns)
print("Coeficientes:")
print(coeficientes.round(3))

# Avaliação
y_pred = modelo.predict(X_test)
r2 = r2_score(y_test, y_pred)
rmse = np.sqrt(mean_squared_error(y_test, y_pred))
print(f"R² (teste): {r2:.3f} | RMSE: {rmse:.2f}g")

⚠️ Cuidados Comuns

  • Correlação ≠ causalidade
  • Verificar outliers e não-linearidade
  • Normalizar variáveis com escalas muito diferentes
  • Usar validação (train/test ou cross-validation)

🎓 Checklist

  • [ ] Calculei correlação entre variáveis
  • [ ] Interpretei matriz de correlação
  • [ ] Modelei regressão simples
  • [ ] Modelei regressão múltipla
  • [ ] Avaliei R² e RMSE

— Próxima: Visualização estatística com Seaborn e Matplotlib (opcional).