A Análise de Variância (ANOVA) é um dos métodos estatísticos mais utilizados quando se deseja comparar as médias de três ou mais grupos independentes em relação a uma variável contínua. Diferente do teste t, que se limita à comparação entre dois grupos, a ANOVA permite avaliar, em um único teste, se existe pelo menos uma diferença estatisticamente significativa entre as médias de múltiplos grupos, controlando a taxa de erro do tipo I que seria inflacionada caso fossem realizadas várias comparações par a par.
Neste relatório, a ANOVA de um fator (one-way ANOVA) é
aplicada ao conjunto de dados PlantGrowth, um dataset
disponível no R, utilizado para fins didáticos em cursos de estatística
experimental. O conjunto contém o peso seco de plantas submetidas a um
grupo controle e a dois tratamentos distintos, permitindo investigar se
o tipo de tratamento influencia o crescimento (peso seco) das
plantas.
O objetivo deste estudo é verificar, por meio de um teste de ANOVA de um fator, se existe diferença estatisticamente significativa no peso seco médio das plantas entre os três grupos experimentais avaliados:
Formalmente, as hipóteses estatísticas testadas são:
Caso a hipótese nula seja rejeitada, um teste complementar Teste post-hoc de Tukey, que faz comparações múltiplas, será aplicado para identificar especificamente quais pares de grupos diferem entre si.
O dataset utilizado é o PlantGrowth, nativo do pacote
datasets do R. Ele é composto por 30
observações e 2 variáveis:
| Variável | Tipo | Descrição |
|---|---|---|
weight |
Numérica | Peso seco da planta (variável resposta) |
group |
Categórica (fator) | Grupo de tratamento: ctrl, trt1,
trt2 |
Para facilitar a interpretação dos resultados, os níveis do fator
group foram traduzidos para o português:
Controle, Tratamento 1 e
Tratamento 2. Cada grupo possui 10
observações, caracterizando um balanceamento.
# Carregando o dataset PlantGrowth
data("PlantGrowth")
# Criando uma cópia para não alterar o dataset original
df_plantas <- PlantGrowth
# Traduzindo os rótulos dos grupos
levels(df_plantas$group) <- c("Controle", "Tratamento 1", "Tratamento 2")
# Quantidade de observações por grupo
cat("Quantidade de amostras por grupo:\n")## Quantidade de amostras por grupo:
##
## Controle Tratamento 1 Tratamento 2
## 10 10 10
## 'data.frame': 30 obs. of 2 variables:
## $ weight: num 4.17 5.58 5.18 6.11 4.5 4.61 5.17 4.53 5.33 5.14 ...
## $ group : Factor w/ 3 levels "Controle","Tratamento 1",..: 1 1 1 1 1 1 1 1 1 1 ...
## weight group
## Min. :3.590 Controle :10
## 1st Qu.:4.550 Tratamento 1:10
## Median :5.155 Tratamento 2:10
## Mean :5.073
## 3rd Qu.:5.530
## Max. :6.310
A metodologia adotada neste relatório segue as seguintes etapas:
aov()), utilizando weight ~ group como
modelo;Todas as análises foram realizadas em linguagem R e Python,
utilizando as funções aov(), shapiro.test(),
bartlett.test() e TukeyHSD(), além do pacote
ggplot2 para a construção dos gráficos.
A ANOVA paramétrica pressupõe que os resíduos do modelo sigam distribuição normal e que as variâncias sejam homogêneas entre os grupos comparados. Essas condições são verificadas a seguir.
qqnorm(residuos_plantas, main = "Gráfico QQ-Plot dos Resíduos")
qqline(residuos_plantas, col = "red", lwd = 2)
grid()Gráfico QQ-Plot dos resíduos do modelo ANOVA
Ao observar o gráfico, os pontos se distribuem, em sua maioria, próximos à reta de referência, sugerindo aderência dos resíduos à distribuição normal, sem desvios sistemáticos relevantes (como caudas pesadas ou assimetria acentuada).
teste_shapiro <- shapiro.test(residuos_plantas)
cat("--- Teste de Normalidade (Shapiro-Wilk) ---\n")## --- Teste de Normalidade (Shapiro-Wilk) ---
## Estatística de teste (W): 0.9661
## p-valor: 4.378986e-01
if (teste_shapiro$p.value > 0.05) {
cat("Resultado: Não rejeitamos H0. Os resíduos seguem uma distribuição normal.\n")
} else {
cat("Resultado: Rejeitamos H0. Os resíduos não seguem uma distribuição normal.\n")
}## Resultado: Não rejeitamos H0. Os resíduos seguem uma distribuição normal.
Como o p-valor obtido é superior ao nível de significância de 0,05, não há evidências para rejeitar a hipótese de normalidade dos resíduos. Esse pressuposto é, portanto, considerado atendido.
teste_bartlett <- bartlett.test(weight ~ group, data = df_plantas)
cat("--- Teste de Homocedasticidade (Bartlett) ---\n")## --- Teste de Homocedasticidade (Bartlett) ---
##
## Bartlett test of homogeneity of variances
##
## data: weight by group
## Bartlett's K-squared = 2.8786, df = 2, p-value = 0.2371
if (teste_bartlett$p.value > 0.05) {
cat("\nResultado: Não rejeitamos H0. As variâncias são homogêneas.\n")
} else {
cat("\nResultado: Rejeitamos H0. As variâncias não são homogêneas.\n")
}##
## Resultado: Não rejeitamos H0. As variâncias são homogêneas.
Como o p-valor do teste de Bartlett também é superior a 0,05, não há evidências de heterogeneidade de variâncias entre os grupos. Assim, o segundo pressuposto da ANOVA é igualmente satisfeito.
Conclusão da verificação de pressupostos: com a normalidade dos resíduos e a homogeneidade das variâncias confirmadas, a aplicação da ANOVA paramétrica é considerada estatisticamente adequada para este conjunto de dados.
Com os pressupostos validados, o teste de ANOVA de um fator é
aplicado, comparando o peso seco médio (weight) entre os
três grupos de tratamento (group).
modelo_plantas <- aov(weight ~ group, data = df_plantas)
tabela_anova_plantas <- summary(modelo_plantas)
cat("--- Tabela ANOVA ---\n")## --- Tabela ANOVA ---
## Df Sum Sq Mean Sq F value Pr(>F)
## group 2 3.766 1.8832 4.846 0.0159 *
## Residuals 27 10.492 0.3886
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
A tabela ANOVA obtida indica:
Como o p-valor é menor que o nível de significância adotado (0,05), rejeita-se a hipótese nula (H0). Conclui-se, com 95% de confiança, que existe diferença estatisticamente significativa entre as médias de peso seco de pelo menos um par de grupos de tratamento.
Para compreender a magnitude do resultado obtido na ANOVA, é fundamental analisar o comportamento do teste sob a ótica das regiões de decisão estatística. A Distribuição F possui uma assimetria positiva contínua que modela a razão entre a variabilidade explicada pelo fator experimental (Tratamento) e a variabilidade residual (Acaso).
A fronteira que delimita a aceitação ou rejeição da hipótese nula (\(H_0\)) é definida pelo F crítico, calculado com base no nível de significância (\(\alpha = 0,05\)) e nos graus de liberdade do modelo (\(df_1 = 2\) e \(df_2 = 27\)). Valores calculados que ultrapassam essa barreira entram na chamada Região Crítica ou Zona de Rejeição, onde a probabilidade de o efeito observado ser fruto de um erro amostral aleatório é inferior a 5%.
O gráfico a seguir ilustra a curva exata de densidade de probabilidade para o desenho amostral deste experimento, mapeando visualmente onde o valor estatístico calculado pelos dados se posiciona.
# 1. Definindo os parâmetros do modelo extraídos da ANOVA
dfn <- 2 # Graus de Liberdade Entre Grupos (Numerador)
dfd <- 27 # Graus de Liberdade Dentro dos Grupos (Denominador)
f_calculado <- 4.846
alpha <- 0.05
# 2. Calculando o F crítico exato usando a função quantil do R
f_critico <- qf(1 - alpha, dfn, dfd)
# 3. Gerando os dados para desenhar a curva F
x_valores <- seq(0, 7, length.out = 500)
dados_curva <- data.frame(
x = x_valores,
y = df(x_valores, dfn, dfd)
)
# 4. Criando subconjuntos de dados para preencher as áreas (Zonas)
dados_aceita <- subset(dados_curva, x <= f_critico)
dados_rejeita <- subset(dados_curva, x > f_critico)
# 5. Construindo o gráfico com ggplot2
ggplot(dados_curva, aes(x = x, y = y)) +
# Preenchimento da Zona de Aceitação (Azul claro)
geom_area(data = dados_aceita, aes(x = x, y = y, fill = "Zona de Aceitação (H0)"), alpha = 0.7) +
# Preenchimento da Zona de Rejeição (Vermelho claro)
geom_area(data = dados_rejeita, aes(x = x, y = y, fill = "Zona de Rejeição (H0)"), alpha = 0.7) +
# Linha de contorno da distribuição F
geom_line(color = "black", size = 1) +
# Linha vertical do F crítico
geom_vline(aes(xintercept = f_critico, color = "F crítico"), linetype = "dashed", size = 1) +
# Linha vertical do Seu F calculado
geom_vline(aes(xintercept = f_calculado, color = "F calculado"), size = 1.2) +
# Ponto indicador em cima do F calculado
geom_point(aes(x = f_calculado, y = df(f_calculado, dfn, dfd)), color = "#e69138", size = 3) +
# Configuração de cores personalizadas (seguindo a paleta do relatório)
scale_fill_manual(values = c("Zona de Aceitação (H0)" = "#cfe2f3", "Zona de Rejeição (H0)" = "#f4cccc")) +
scale_color_manual(values = c("F crítico" = "#cc0000", "F calculado" = "#e69138")) +
# Títulos e rótulos
labs(
title = "Distribuição F do Experimento PlantGrowth",
subtitle = paste("Graus de Liberdade:", dfn, "e", dfd, "| F Crítico =", round(f_critico, 3)),
x = "Valor F",
y = "Densidade de Probabilidade",
fill = "Regiões de Decisão",
color = "Linhas de Referência"
) +
# Definição do tema visual (limpo e profissional)
theme_minimal(base_size = 12) +
theme(
plot.title = element_text(face = "bold", size = 14),
legend.position = "right",
panel.grid.minor = element_blank()
) +
scale_x_continuous(limits = c(0, 7), breaks = 0:7)Zonas de Aceitação e Rejeição para a Distribuição F(2, 27)
A análise visual do gráfico confirma a decisão estatística tomada de forma inequívoca. A linha vertical pontilhada em vermelho estabelece o limite do F crítico em 3,354. Toda a área sombreada em vermelho à direita dessa linha representa os 5% de resultados mais extremos possíveis caso os tratamentos fossem idênticos.
Como o modelo obteve um F calculado de 4,846 (representado pela linha laranja), observa-se que ele ultrapassa a fronteira limitante e localiza-se na Zona de Rejeição. Esse distanciamento em relação à Zona de Aceitação (área azul) comprova visualmente que o impacto dos tratamentos sobre o peso seco das plantas supera o ruído natural do experimento, validando a necessidade de prosseguir para as análises de comparações múltiplas.
Como a ANOVA indicou diferença significativa entre os grupos, aplica-se o teste de comparações múltiplas de Tukey para identificar especificamente entre quais pares de grupos essa diferença ocorre.
## --- Teste de Comparações Múltiplas de Tukey ---
## Tukey multiple comparisons of means
## 95% family-wise confidence level
##
## Fit: aov(formula = weight ~ group, data = df_plantas)
##
## $group
## diff lwr upr p adj
## Tratamento 1-Controle -0.371 -1.0622161 0.3202161 0.3908711
## Tratamento 2-Controle 0.494 -0.1972161 1.1852161 0.1979960
## Tratamento 2-Tratamento 1 0.865 0.1737839 1.5562161 0.0120064
A coluna p adj indica o p-valor ajustado para múltiplas
comparações, e a coluna implícita de significância pode ser verificada
observando se o intervalo de confiança (lwr,
upr) contém o valor zero. Quando o intervalo não contém
zero e o p-valor ajustado é inferior a 0,05, considera-se que existe
diferença estatisticamente significativa entre aquele par específico de
grupos.
ggplot(df_plantas, aes(x = group, y = weight, fill = group)) +
geom_boxplot(alpha = 0.7) +
geom_jitter(width = 0.15, color = "black", alpha = 0.5, size = 2) +
labs(
title = "Distribuição do Peso das Plantas por Tipo de Tratamento",
x = "Grupo de Tratamento",
y = "Peso Seco da Planta"
) +
scale_fill_brewer(palette = "Pastel1") +
theme_minimal() +
theme(
plot.title = element_text(face = "bold"),
panel.grid.major.x = element_blank(),
legend.position = "none"
)Distribuição do peso seco das plantas por grupo de tratamento
O boxplot evidencia que o Tratamento 2 apresenta a maior mediana de peso seco entre os três grupos, seguido pelo grupo Controle, enquanto o Tratamento 1 apresenta a menor mediana e a maior dispersão de valores, com sobreposição parcial das distribuições entre os grupos.
resumo_grupos <- aggregate(weight ~ group, data = df_plantas,
FUN = function(x) c(media = mean(x), sd = sd(x), n = length(x)))
resumo_grupos <- do.call(data.frame, resumo_grupos)
names(resumo_grupos) <- c("group", "media", "sd", "n")
resumo_grupos$erro_padrao <- resumo_grupos$sd / sqrt(resumo_grupos$n)
resumo_grupos$ic95 <- qt(0.975, df = resumo_grupos$n - 1) * resumo_grupos$erro_padrao
ggplot(resumo_grupos, aes(x = group, y = media)) +
geom_point(size = 3, color = "#2c7fb8") +
geom_errorbar(aes(ymin = media - ic95, ymax = media + ic95),
width = 0.1, color = "#2c7fb8") +
labs(
title = "Média de Peso por Tratamento (IC 95%)",
x = "Grupo de Tratamento",
y = "Peso Médio"
) +
theme_minimal() +
theme(plot.title = element_text(face = "bold"))Peso médio por tratamento, com intervalo de confiança de 95%
Intervalos de confiança das diferenças entre pares de grupos (Tukey HSD)
Neste gráfico, os intervalos de confiança que não cruzam a linha vertical em zero indicam diferenças estatisticamente significativas entre o respectivo par de grupos.
Para comparativos, acesse os códigos em Python nesse link: https://colab.research.google.com/drive/15EH1mTstExkhTyU5MyEA3XYAIZwduzc-?usp=sharing
Os resultados obtidos permitem algumas considerações relevantes sobre o efeito dos tratamentos aplicados:
É importante destacar que a significância estatística encontrada não implica, necessariamente, relevância prática de grande magnitude — o tamanho da amostra (10 observações por grupo) é reduzido, o que reforça a importância de estudos futuros com maior poder estatístico para consolidar essas conclusões.
A partir da aplicação da ANOVA de um fator ao conjunto de dados
PlantGrowth, conclui-se que:
Esses achados demonstram a utilidade da ANOVA como ferramenta para comparação de múltiplos grupos experimentais e reforçam a importância da verificação prévia dos pressupostos estatísticos antes da aplicação do teste, de forma a garantir a validade das conclusões obtidas.
Oliveira, Bruno. “Análise de Variância (ANOVA): Suas Aplicações E Resultados.” Statplace, 16 Aug. 2019, statplace.com.br/blog/como-interpretar-analise-de-variancia-anova/.
Stephanie. “Welch’s ANOVA: Definition, Assumptions.” Statistics How To, 20 Oct. 2016, www.statisticshowto.com/welchs-anova/.
Arunn Thevapalan. “Teste ANOVA: Um Guia Detalhado Com Exemplos.” Datacamp.com, DataCamp, Oct. 2024, www.datacamp.com/pt/tutorial/anova-test.
C. Reiter, Amanda, et al. “Tutorial ANOVA.” RPubs, 24 Oct. 2019, www.rpubs.com/dangs12/tutorial_anova.