18  Modelos Lineares Generalizados - GLM

A Análise de Variância (ANOVA) (e os testes t) são ferramentas estatísticas fundamentais para comparar médias entre dois ou mais grupos. Esses métodos são poderosos quando seus pressupostos são atendidos, como a normalidade dos resíduos e a homogeneidade das variâncias. No entanto, na pesquisa em ciências agrárias, biológicas e ambientais, frequentemente nos deparamos com dados que não se encaixam perfeitamente nesses moldes

Muitas variáveis resposta de interesse não seguem uma distribuição normal, ou suas variâncias não são constantes entre os grupos. Pense, por exemplo, em:

Tentar ajustar modelos lineares clássicos a esses tipos de dados pode levar a predições irrealistas (como contagens negativas), erros padrão incorretos e, consequentemente, a conclusões estatísticas equivocadas. É aqui que entram os Modelos Lineares Generalizados (GLM), que nos permitem analisar uma gama muito mais ampla de variáveis resposta. Eles mantêm a estrutura familiar de um preditor linear, mas introduzem duas modificações cruciais:

Exemplo 18.1 (GLM - distribuição de Poisson) No manejo integrado de pragas, a seleção de variedades ou genótipos de plantas menos suscetíveis ao ataque de insetos-praga é uma estratégia fundamental. Um grupo de pesquisadores em entomologia agrícola está investigando a resposta de uma espécie de besouro-praga a diferentes genótipos de uma determinada cultura. O objetivo é identificar se alguns genótipos são mais ou menos preferidos (ou suscetíveis) pelo besouro, o que poderia ter implicações diretas para programas de melhoramento genético e recomendações de plantio.

Para avaliar essa questão, foi conduzido um experimento com oito diferentes genótipos da planta hospedeira. Após um período de exposição padronizado, o número de besouros adultos encontrados em cada unidade experimental foi contado. Os dados estão no arquivo besouro.csv.

Dado que a variável resposta é uma contagem, um Modelo Linear Generalizado (GLM) com distribuição de Poisson e função de ligação logarítmica é proposto como a abordagem adequada para investigar o efeito do fator variedade sobre o número de insetos.

Calcular estatísticas descritivas por grupo:

besouro |>
  group_by(variedade) |>
  summarise(
    n = n(),
    media = mean(n.inseto),
    desvpad = sd(n.inseto),
    var = var(n.inseto)
  )
# A tibble: 8 × 5
  variedade     n  media desvpad     var
  <fct>     <int>  <dbl>   <dbl>   <dbl>
1 test          4 225.    21.2   449.   
2 v1            4   1.75   0.957   0.917
3 v2            4   5      1.63    2.67 
4 v3            4   5.75   2.22    4.92 
5 v4            4   6.25   2.22    4.92 
6 v5            4   7.75   2.06    4.25 
7 v6            4  34.8    3.30   10.9  
8 v7            4  43.8    3.30   10.9  

Boxplot comparativo entre os grupos

besouro |>
  ggplot(aes(x = variedade, y = n.inseto)) +
  geom_boxplot() +
  labs(
    x = "Variedades",
    y = "Número de insetos"
  ) +
  theme_classic()

Ajuste do modelo com distribuição de Poisson

# Ajustar o modelo de Poisson com log link
glm_besouro <- glm(n.inseto ~ variedade,
  family = poisson(link = "log"),
  data = besouro
)
anova(glm_besouro)
Analysis of Deviance Table

Model: poisson, link: log

Response: n.inseto

Terms added sequentially (first to last)

          Df Deviance Resid. Df Resid. Dev  Pr(>Chi)    
NULL                         31    2630,07              
variedade  7   2612,6        24      17,44 < 2,2e-16 ***
---
Signif. codes:  0 '***' 0,001 '**' 0,01 '*' 0,05 '.' 0,1 ' ' 1
# Verificar o Índice de dispersão: razão Deviance Residual / Graus de Liberdade Residuais.
# Se este valor for > 1.5-2.0, a superdispersão pode ser um problema.
deviance(glm_besouro) / df.residual(glm_besouro)
[1] 0,726811
# Gráfico de Resíduos vs. Valores Ajustados
# Resíduos não devem mostrar padrões sistemáticos
plot(glm_besouro, which = 1)

Teste de Tukey para o efeito da variedade

# Carregar pacotes se ainda não estiverem carregados
pacman::p_load("emmeans", "multcomp", "multcompView")


# Calcular as médias marginais estimadas e aplicar o teste de Tukey
tk_variedade <- emmeans::emmeans(glm_besouro, ~variedade, contr = "tukey")


# Contrastes (comparações par a par)
tk_variedade$contrasts
 contrast  estimate     SE  df z.ratio p.value
 test - v1   4,8576 0,3790 Inf  12,802  0,0000
 test - v2   3,8078 0,2260 Inf  16,843  0,0000
 test - v3   3,6680 0,2110 Inf  17,371  0,0000
 test - v4   3,5846 0,2030 Inf  17,680  0,0000
 test - v5   3,3695 0,1830 Inf  18,446  0,0000
 test - v6   1,8690 0,0911 Inf  20,510  0,0000
 test - v7   1,6387 0,0826 Inf  19,837  0,0000
 v1 - v2    -1,0498 0,4390 Inf  -2,391  0,2458
 v1 - v3    -1,1896 0,4320 Inf  -2,756  0,1064
 v1 - v4    -1,2730 0,4280 Inf  -2,977  0,0585
 v1 - v5    -1,4881 0,4180 Inf  -3,556  0,0090
 v1 - v6    -2,9886 0,3870 Inf  -7,715  0,0000
 v1 - v7    -3,2189 0,3850 Inf  -8,351  0,0000
 v2 - v3    -0,1398 0,3060 Inf  -0,457  0,9998
 v2 - v4    -0,2231 0,3000 Inf  -0,744  0,9956
 v2 - v5    -0,4383 0,2870 Inf  -1,528  0,7924
 v2 - v6    -1,9387 0,2390 Inf  -8,107  0,0000
 v2 - v7    -2,1691 0,2360 Inf  -9,189  0,0000
 v3 - v4    -0,0834 0,2890 Inf  -0,289  1,0000
 v3 - v5    -0,2985 0,2750 Inf  -1,085  0,9602
 v3 - v6    -1,7990 0,2250 Inf  -7,992  0,0000
 v3 - v7    -2,0293 0,2220 Inf  -9,149  0,0000
 v4 - v5    -0,2151 0,2690 Inf  -0,800  0,9932
 v4 - v6    -1,7156 0,2170 Inf  -7,897  0,0000
 v4 - v7    -1,9459 0,2140 Inf  -9,101  0,0000
 v5 - v6    -1,5005 0,1990 Inf  -7,554  0,0000
 v5 - v7    -1,7308 0,1950 Inf  -8,882  0,0000
 v6 - v7    -0,2303 0,1140 Inf  -2,027  0,4633

Results are given on the log (not the response) scale. 
P value adjustment: tukey method for comparing a family of 8 estimates 
# Intervalos de confiança para os contrastes
tk_variedade$contrasts |> confint()
 contrast  estimate     SE  df asymp.LCL asymp.UCL
 test - v1   4,8576 0,3790 Inf     3,708    6,0076
 test - v2   3,8078 0,2260 Inf     3,123    4,4930
 test - v3   3,6680 0,2110 Inf     3,028    4,3080
 test - v4   3,5846 0,2030 Inf     2,970    4,1992
 test - v5   3,3695 0,1830 Inf     2,816    3,9232
 test - v6   1,8690 0,0911 Inf     1,593    2,1452
 test - v7   1,6387 0,0826 Inf     1,388    1,8891
 v1 - v2    -1,0498 0,4390 Inf    -2,381    0,2812
 v1 - v3    -1,1896 0,4320 Inf    -2,498    0,1187
 v1 - v4    -1,2730 0,4280 Inf    -2,569    0,0231
 v1 - v5    -1,4881 0,4180 Inf    -2,756   -0,2198
 v1 - v6    -2,9886 0,3870 Inf    -4,163   -1,8145
 v1 - v7    -3,2189 0,3850 Inf    -4,387   -2,0506
 v2 - v3    -0,1398 0,3060 Inf    -1,066    0,7869
 v2 - v4    -0,2231 0,3000 Inf    -1,132    0,6861
 v2 - v5    -0,4383 0,2870 Inf    -1,308    0,4310
 v2 - v6    -1,9387 0,2390 Inf    -2,664   -1,2139
 v2 - v7    -2,1691 0,2360 Inf    -2,884   -1,4536
 v3 - v4    -0,0834 0,2890 Inf    -0,959    0,7923
 v3 - v5    -0,2985 0,2750 Inf    -1,133    0,5356
 v3 - v6    -1,7990 0,2250 Inf    -2,481   -1,1167
 v3 - v7    -2,0293 0,2220 Inf    -2,702   -1,3571
 v4 - v5    -0,2151 0,2690 Inf    -1,030    0,5996
 v4 - v6    -1,7156 0,2170 Inf    -2,374   -1,0572
 v4 - v7    -1,9459 0,2140 Inf    -2,594   -1,2979
 v5 - v6    -1,5005 0,1990 Inf    -2,102   -0,8985
 v5 - v7    -1,7308 0,1950 Inf    -2,321   -1,1402
 v6 - v7    -0,2303 0,1140 Inf    -0,575    0,1140

Results are given on the log (not the response) scale. 
Confidence level used: 0,95 
Conf-level adjustment: tukey method for comparing a family of 8 estimates 
# Médias marginais estimadas e Compact Letter Display (CLD)
## Ajustar 'Letters = letters' ou 'Letters = LETTERS' para minúsculas ou maiúsculas
## Ajustar decreasing = TRUE para letras decrescentes e decreasing = FALSE para crescentes
tk_variedade$emmeans |> multcomp::cld(Letters = letters, decreasing = TRUE)
 variedade emmean     SE  df asymp.LCL asymp.UCL .group
 test        5,42 0,0333 Inf     5,352      5,48  a    
 v7          3,78 0,0756 Inf     3,630      3,93   b   
 v6          3,55 0,0848 Inf     3,382      3,71   b   
 v5          2,05 0,1800 Inf     1,696      2,40    c  
 v4          1,83 0,2000 Inf     1,441      2,22    cd 
 v3          1,75 0,2090 Inf     1,341      2,16    cd 
 v2          1,61 0,2240 Inf     1,171      2,05    cd 
 v1          0,56 0,3780 Inf    -0,181      1,30     d 

Results are given on the log (not the response) scale. 
Confidence level used: 0,95 
P value adjustment: tukey method for comparing a family of 8 estimates 
significance level used: alpha = 0,05 
NOTE: If two or more means share the same grouping symbol,
      then we cannot show them to be different.
      But we also did not show them to be the same. 
tk_variedade$emmeans |> multcomp::cld(Letters = letters, decreasing = TRUE, type = "response")
 variedade   rate    SE  df asymp.LCL asymp.UCL .group
 test      225,25 7,500 Inf   211,012    240,45  a    
 v7         43,75 3,310 Inf    37,725     50,74   b   
 v6         34,75 2,950 Inf    29,428     41,03   b   
 v5          7,75 1,390 Inf     5,450     11,02    c  
 v4          6,25 1,250 Inf     4,223      9,25    cd 
 v3          5,75 1,200 Inf     3,821      8,65    cd 
 v2          5,00 1,120 Inf     3,226      7,75    cd 
 v1          1,75 0,661 Inf     0,834      3,67     d 

Confidence level used: 0,95 
Intervals are back-transformed from the log scale 
P value adjustment: tukey method for comparing a family of 8 estimates 
Tests are performed on the log scale 
significance level used: alpha = 0,05 
NOTE: If two or more means share the same grouping symbol,
      then we cannot show them to be different.
      But we also did not show them to be the same. 
# Gráfico das médias com intervalo de confiança
tk_variedade$emmeans |> plot(comparisons = TRUE, CIs = TRUE, type = "response")

Exemplo 18.2 (GLM - Distribuição binomial) Uma empresa de sementes está desenvolvendo e testando novos tratamentos para melhorar a taxa de germinação de uma espécie de hortaliça de alto valor comercial. Quatro tratamentos (um controle e três novos tratamentos experimentais: T1, T2, T3) foram aplicados a lotes de sementes.

Para cada um dos quatro tratamentos, foram preparadas cinco repetições (caixas de germinação). Em cada repetição, um número fixo de 50 sementes foi semeado. Após um período de incubação, contou-se o número de sementes que germinaram em cada uma das unidades experimentais. Os dados estão no arquivo germinacao.csv.

Os pesquisadores desejam determinar se existem diferenças estatisticamente significativas na proporção média de germinação entre os diferentes tratamentos. Dado que a variável resposta é o número de sementes germinadas de um total conhecido, um Modelo Linear Generalizado (GLM) com distribuição Binomial e função de ligação logística (logit) é a abordagem apropriada para investigar o efeito do fator tratamento sobre a proporção de germinação.

Calcular estatísticas descritivas por grupo:

germinacao |>
  group_by(tratamento) |>
  summarise(
    n = n(),
    media = mean(germinadas),
    desvpad = sd(germinadas),
    var = var(germinadas)
  )
# A tibble: 4 × 5
  tratamento     n media desvpad   var
  <fct>      <int> <dbl>   <dbl> <dbl>
1 Controle       5  18.2    2.17   4.7
2 T1             5  29      5.70  32.5
3 T2             5  37.6    1.67   2.8
4 T3             5  41.4    2.07   4.3

Boxplot comparativo entre os grupos

germinacao |>
  ggplot(aes(x = tratamento, y = germinadas)) +
  geom_boxplot() +
  labs(
    x = "Tratamento de sementes",
    y = "Número de sementes germinadas"
  ) +
  theme_classic()

Ajuste do modelo com distribuição Binomial

# A variável resposta para family=binomial pode ser uma matriz de duas colunas:
# coluna 1 = número de sucessos (germinadas)
# coluna 2 = número de fracassos (nao_germinadas)
# Alternativamente, pode ser uma proporção (germinadas/total_sementes)
# com a variável total_sementes passada para o argumento 'weights'.
# A abordagem com matriz de duas colunas é geralmente preferida.

glm_germinacao <- glm(cbind(germinadas, nao_germinadas) ~ tratamento,
  family = binomial(link = "logit"),
  data = germinacao
)
anova(glm_germinacao)
Analysis of Deviance Table

Model: binomial, link: logit

Response: cbind(germinadas, nao_germinadas)

Terms added sequentially (first to last)

           Df Deviance Resid. Df Resid. Dev  Pr(>Chi)    
NULL                          19    155,903              
tratamento  3   139,27        16     16,634 < 2,2e-16 ***
---
Signif. codes:  0 '***' 0,001 '**' 0,01 '*' 0,05 '.' 0,1 ' ' 1
# Verificar o Índice de dispersão (Overdispersion)
# Para dados binomiais, idealmente próximo de 1.
# Valores > 1.5-2.0 podem indicar superdispersão.
deviance(glm_germinacao) / df.residual(glm_germinacao)
[1] 1,03965
# Gráfico de Resíduos vs. Valores Ajustados
# Resíduos não devem mostrar padrões sistemáticos
plot(glm_germinacao, which = 1)

Teste de Tukey para o efeito do tratamento de sementes

# Carregar pacotes se ainda não estiverem carregados
pacman::p_load("emmeans", "multcomp", "multcompView")


# Calcular as médias marginais estimadas e aplicar o teste de Tukey
tk_germinacao <- emmeans::emmeans(glm_germinacao, ~tratamento, contr = "tukey")


# Contrastes (comparações par a par)
tk_germinacao$contrasts
 contrast      estimate    SE  df z.ratio p.value
 Controle - T1   -0,881 0,184 Inf  -4,798  0,0000
 Controle - T2   -1,667 0,197 Inf  -8,473  0,0000
 Controle - T3   -2,130 0,213 Inf  -9,998  0,0000
 T1 - T2         -0,787 0,195 Inf  -4,042  0,0003
 T1 - T3         -1,249 0,211 Inf  -5,919  0,0000
 T2 - T3         -0,462 0,223 Inf  -2,077  0,1607

Results are given on the log odds ratio (not the response) scale. 
P value adjustment: tukey method for comparing a family of 4 estimates 
# Intervalos de confiança para os contrastes
tk_germinacao$contrasts |> confint()
 contrast      estimate    SE  df asymp.LCL asymp.UCL
 Controle - T1   -0,881 0,184 Inf     -1,35    -0,409
 Controle - T2   -1,667 0,197 Inf     -2,17    -1,162
 Controle - T3   -2,130 0,213 Inf     -2,68    -1,582
 T1 - T2         -0,787 0,195 Inf     -1,29    -0,287
 T1 - T3         -1,249 0,211 Inf     -1,79    -0,707
 T2 - T3         -0,462 0,223 Inf     -1,03     0,110

Results are given on the log odds ratio (not the response) scale. 
Confidence level used: 0,95 
Conf-level adjustment: tukey method for comparing a family of 4 estimates 
# Médias marginais estimadas e Compact Letter Display (CLD)
## Ajustar 'Letters = letters' ou 'Letters = LETTERS' para minúsculas ou maiúsculas
## Ajustar decreasing = TRUE para letras decrescentes e decreasing = FALSE para crescentes
tk_germinacao$emmeans |> multcomp::cld(Letters = letters, decreasing = TRUE)
 tratamento emmean    SE  df asymp.LCL asymp.UCL .group
 T3          1,572 0,168 Inf    1,2430     1,900  a    
 T2          1,109 0,146 Inf    0,8223     1,396  a    
 T1          0,323 0,128 Inf    0,0716     0,574   b   
 Controle   -0,558 0,131 Inf   -0,8157    -0,300    c  

Results are given on the logit (not the response) scale. 
Confidence level used: 0,95 
Results are given on the log odds ratio (not the response) scale. 
P value adjustment: tukey method for comparing a family of 4 estimates 
significance level used: alpha = 0,05 
NOTE: If two or more means share the same grouping symbol,
      then we cannot show them to be different.
      But we also did not show them to be the same. 
tk_germinacao$emmeans |> multcomp::cld(Letters = letters, decreasing = TRUE, type = "response")
 tratamento  prob     SE  df asymp.LCL asymp.UCL .group
 T3         0,828 0,0239 Inf     0,776     0,870  a    
 T2         0,752 0,0273 Inf     0,695     0,802  a    
 T1         0,580 0,0312 Inf     0,518     0,640   b   
 Controle   0,364 0,0304 Inf     0,307     0,425    c  

Confidence level used: 0,95 
Intervals are back-transformed from the logit scale 
P value adjustment: tukey method for comparing a family of 4 estimates 
Tests are performed on the log odds ratio scale 
significance level used: alpha = 0,05 
NOTE: If two or more means share the same grouping symbol,
      then we cannot show them to be different.
      But we also did not show them to be the same. 
# Gráfico das médias com intervalo de confiança
tk_germinacao$emmeans |> plot(comparisons = TRUE, CIs = TRUE, type = "response")