Análise de variância (ANOVA) e testes de médias são métodos comuns em artigos científicos. Você com certeza já viu aquelas letrinhas indicando a diferença entre tratamentos em algum estudo publicado. Por mais que este método esteja entrando em desuso - há uma tendência em abandonar esse tipo de abordagem estatística - penso que ainda o veremos por muitos anos no meio científico.

Como contexto, temos um teste de 5 progênies de eucalipto e queremos avaliar se volume por hectare (nossa variável resposta), difere entre os tratamentos.

Pois bem, para percebermos a dimensão dos dados e qual a variabilidade de cada tratamento, vamos criar um boxplot (Figura 1). Caso você queira saber um pouco mais sobre este tipo de gráfico, veja o post sobre ele.

if (!require("pacman")) install.packages("pacman")
pacman::p_load(readr, dplyr, tibble, ggplot2, car, agricolae)
dados <- read_csv2(
  "https://github.com/italocegatta/italocegatta.github.io_source/raw/master/content/dados/base_progenie.csv"
)

dados
## # A tibble: 30 x 3
##    repeticao progenie volume
##        <dbl> <chr>     <dbl>
##  1         1 A           212
##  2         2 A           206
##  3         3 A           224
##  4         4 A           289
##  5         5 A           324
##  6         6 A           219
##  7         1 B           108
##  8         2 B           194
##  9         3 B           163
## 10         4 B           111
## # ... with 20 more rows
ggplot(dados, aes(progenie, volume)) +
  geom_boxplot(fill = "grey60", alpha = 0.8) +
  theme_bw(16)
Variabilidade do volume por hectare de cada tratamento.

Figura 1: Variabilidade do volume por hectare de cada tratamento.

A ANOVA é um método bastante consolidado no meio acadêmico. Basicamente, este método informa se existe um tratamento discrepante dentre os demais. Entretanto, ele exige que algumas premissas sejam atendidas, como: distribuição normal dos resíduos e homogeneidade de variância.

Primeiro, vamos utilizar o teste de Levene para verificar se há homogeneidade de variância, ou homocedasticidade. Como o p-valor é maior que 5% não temos evidência significativa para rejeitar a hipótese nula de homogeneidade, ou seja, nossos dados tem homogeneidade de variância.

leveneTest(volume ~ factor(progenie), data=dados)
## Levene's Test for Homogeneity of Variance (center = median)
##       Df F value  Pr(>F)  
## group  4  2.4677 0.07086 .
##       25                  
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

O segundo pressuposto é a normalidade dos resíduos. Utilizaremos o teste de Shapiro-Wilk cuja hipótese nula é a de que os dados seguem uma distribuição normal. Como o p-valor é superior ao limite de 5%, podemos aceitar a hipótese nula e considerar nossos dados normais.

anova <-  aov(volume ~ progenie, data=dados)

shapiro.test(resid(anova))
## 
##  Shapiro-Wilk normality test
## 
## data:  resid(anova)
## W = 0.96097, p-value = 0.3279

Uma vez que os pressupostos foram atendidos, seguiremos para a ANOVA. Note que, caso os testes de Levene e Shapiro-Wilk resultassem em um p-valor significante, ou seja, menor que 5%, teríamos que utilizar outro método estatístico para analisar nossos dados. Nesse caso, uma alternativa é utilizar testes não-paramétricos, uma vez que eles não exigem os pressupostos que acabamos de testar.

Nossa ANOVA resultou em um p-valor menor que 5%, portanto, temos evidências de que ao menos um tratamento se diferencia dos demais. Isso já é uma resposta, mas pouco acrescenta à nossa pesquisa pois queremos saber quem é este tratamento discrepante. Ou melhor, queremos poder comparar os tratamentos entre si e verificar quais são estatisticamente iguais ou diferentes.

summary(anova)
##             Df Sum Sq Mean Sq F value   Pr(>F)    
## progenie     4  86726   21681    8.89 0.000131 ***
## Residuals   25  60974    2439                     
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

Para esta abordagem existem alguns testes de médias e cada um tem uma particularidade, mas de longe o mais utilizado é o de Tukey.

A interpretação do teste de Tukey é simples. Após determinarmos a diferença mínima significativa (ou Honest Significant Difference - HSD), podemos julgar se as médias são iguais ou não. Em termos práticos, esse valor nos dá uma margem de igualdade, pois se a diferença entre dois tratamentos for maior do que isso, os médias são diferentes.

A análise começa sempre pela maior média, no nosso caso a progênie A (245, 66). Com uma continha rápida, a média do tratamento A menos a diferença mínima significativa 245,66 - 83,73 = 161,93, aceitaremos que um tratamento é igual ao A se a média dele for maior que 161,93. O tratamento subsequente (o segundo do ranking) é a progênie D e como sua média é maior que 161,93 podemos dizer que ela é estatisticamente igual a progênie A.

As próximas comparações seguem a mesma lógica. Quando registramos que duas médias são iguais, nós as rotulamos com a mesma letra para facilitar a identificação. Veja no fim do output as letras evidenciando a igualdade entre os tratamentos.

tukey <- HSD.test(anova, "progenie")

tukey
## $statistics
##    MSerror Df     Mean       CV      MSD
##   2438.953 25 165.7667 29.79233 83.73866
## 
## $parameters
##    test   name.t ntr StudentizedRange alpha
##   Tukey progenie   5         4.153363  0.05
## 
## $means
##     volume      std r Min Max    Q25   Q50    Q75
## A 245.6667 48.78798 6 206 324 213.75 221.5 272.75
## B 159.6667 49.47996 6 108 236 119.75 154.5 186.25
## C  80.5000 15.60449 6  63 100  70.00  76.5  93.50
## D 190.1667 75.37484 6 100 267 121.75 207.0 251.75
## E 152.8333 37.96534 6 106 210 133.75 141.5 175.50
## 
## $comparison
## NULL
## 
## $groups
##     volume groups
## A 245.6667      a
## D 190.1667     ab
## B 159.6667     bc
## E 152.8333     bc
## C  80.5000      c
## 
## attr(,"class")
## [1] "group"

Para deixar mais visual ainda, podemos construir um gráfico de barras com a média de cada tratamento e adicionar a sua letra correspondente ao teste de Tukey (Figura 2).

tukey$groups %>% 
  rownames_to_column(var = "trt") %>% 
  mutate(trt = reorder(trt, -volume, mean)) %>% 
  ggplot(aes(trt, volume)) +
    geom_col(alpha = 0.8, color = "black") +
    geom_text(aes(label = groups), vjust = 1.8, size = 9, color = "white") +
    labs(x = "Progênies", y = "Médias") +
    theme_bw(16)
Médias dos tratamentos. As letras indicam médias estatisticamente iguais pelo teste de Tukey a 5% de significância.

Figura 2: Médias dos tratamentos. As letras indicam médias estatisticamente iguais pelo teste de Tukey a 5% de significância.

Caso tenha alguma dúvida ou sugestão sobre o post, fique à vontade para fazer um comentário ou me contatar por E-mail.

sessioninfo::session_info(c("readr", "dplyr", "tibble", "ggplot2", "car", "agricolae"))
## - Session info ----------------------------------------------------------
##  setting  value                       
##  version  R version 3.5.3 (2019-03-11)
##  os       Windows 10 x64              
##  system   x86_64, mingw32             
##  ui       RTerm                       
##  language (EN)                        
##  collate  Portuguese_Brazil.1252      
##  ctype    Portuguese_Brazil.1252      
##  tz       America/Sao_Paulo           
##  date     2019-08-25                  
## 
## - Packages --------------------------------------------------------------
##  package      * version   date       lib source        
##  abind          1.4-5     2016-07-21 [1] CRAN (R 3.5.0)
##  agricolae    * 1.3-1     2019-04-04 [1] CRAN (R 3.5.3)
##  AlgDesign      1.1-7.3   2014-10-15 [1] CRAN (R 3.5.2)
##  assertthat     0.2.1     2019-03-21 [1] CRAN (R 3.5.3)
##  backports      1.1.4     2019-04-10 [1] CRAN (R 3.5.3)
##  BH             1.69.0-1  2019-01-07 [1] CRAN (R 3.5.2)
##  boot           1.3-20    2017-08-06 [2] CRAN (R 3.5.3)
##  car          * 3.0-3     2019-05-27 [1] CRAN (R 3.5.3)
##  carData      * 3.0-2     2018-09-30 [1] CRAN (R 3.5.2)
##  cellranger     1.1.0     2016-07-27 [1] CRAN (R 3.5.1)
##  class          7.3-15    2019-01-01 [2] CRAN (R 3.5.3)
##  classInt       0.4-1     2019-08-06 [1] CRAN (R 3.5.3)
##  cli            1.1.0     2019-03-19 [1] CRAN (R 3.5.3)
##  clipr          0.7.0     2019-07-23 [1] CRAN (R 3.5.3)
##  cluster        2.0.7-1   2018-04-13 [2] CRAN (R 3.5.3)
##  coda           0.19-3    2019-07-05 [1] CRAN (R 3.5.3)
##  colorspace     1.4-1     2019-03-18 [1] CRAN (R 3.5.3)
##  combinat       0.0-8     2012-10-29 [1] CRAN (R 3.5.2)
##  crayon         1.3.4     2017-09-16 [1] CRAN (R 3.5.1)
##  curl           4.0       2019-07-22 [1] CRAN (R 3.5.3)
##  data.table     1.12.2    2019-04-07 [1] CRAN (R 3.5.3)
##  DBI            1.0.0     2018-05-02 [1] CRAN (R 3.5.1)
##  deldir         0.1-23    2019-07-31 [1] CRAN (R 3.5.3)
##  digest         0.6.20    2019-07-04 [1] CRAN (R 3.5.3)
##  dplyr        * 0.8.3     2019-07-04 [1] CRAN (R 3.5.3)
##  e1071          1.7-2     2019-06-05 [1] CRAN (R 3.5.3)
##  ellipsis       0.2.0.1   2019-07-02 [1] CRAN (R 3.5.3)
##  expm           0.999-4   2019-03-21 [1] CRAN (R 3.5.3)
##  fansi          0.4.0     2018-10-05 [1] CRAN (R 3.5.1)
##  forcats        0.4.0     2019-02-17 [1] CRAN (R 3.5.2)
##  foreign        0.8-71    2018-07-20 [2] CRAN (R 3.5.3)
##  gdata          2.18.0    2017-06-06 [1] CRAN (R 3.5.2)
##  ggplot2      * 3.2.1     2019-08-10 [1] CRAN (R 3.5.3)
##  glue           1.3.1     2019-03-12 [1] CRAN (R 3.5.3)
##  gmodels        2.18.1    2018-06-25 [1] CRAN (R 3.5.2)
##  gtable         0.3.0     2019-03-25 [1] CRAN (R 3.5.3)
##  gtools         3.8.1     2018-06-26 [1] CRAN (R 3.5.2)
##  haven          2.1.1     2019-07-04 [1] CRAN (R 3.5.3)
##  highr          0.8       2019-03-20 [1] CRAN (R 3.5.3)
##  hms            0.5.0     2019-07-09 [1] CRAN (R 3.5.3)
##  htmltools      0.3.6     2017-04-28 [1] CRAN (R 3.5.1)
##  httpuv         1.5.1     2019-04-05 [1] CRAN (R 3.5.3)
##  jsonlite       1.6       2018-12-07 [1] CRAN (R 3.5.2)
##  KernSmooth     2.23-15   2015-06-29 [2] CRAN (R 3.5.3)
##  klaR           0.6-14    2018-03-19 [1] CRAN (R 3.5.2)
##  labeling       0.3       2014-08-23 [1] CRAN (R 3.5.0)
##  labelled       2.2.1     2019-05-26 [1] CRAN (R 3.5.3)
##  later          0.8.0     2019-02-11 [1] CRAN (R 3.5.2)
##  lattice        0.20-38   2018-11-04 [2] CRAN (R 3.5.3)
##  lazyeval       0.2.2     2019-03-15 [1] CRAN (R 3.5.3)
##  LearnBayes     2.15.1    2018-03-18 [1] CRAN (R 3.5.2)
##  lme4           1.1-21    2019-03-05 [1] CRAN (R 3.5.3)
##  magrittr       1.5       2014-11-22 [1] CRAN (R 3.5.1)
##  maptools       0.9-5     2019-02-18 [1] CRAN (R 3.5.2)
##  MASS           7.3-51.1  2018-11-01 [2] CRAN (R 3.5.3)
##  Matrix         1.2-17    2019-03-22 [1] CRAN (R 3.5.3)
##  MatrixModels   0.4-1     2015-08-22 [1] CRAN (R 3.5.2)
##  mgcv           1.8-28    2019-03-21 [1] CRAN (R 3.5.3)
##  mime           0.7       2019-06-11 [1] CRAN (R 3.5.3)
##  miniUI         0.1.1.1   2018-05-18 [1] CRAN (R 3.5.2)
##  minqa          1.2.4     2014-10-09 [1] CRAN (R 3.5.1)
##  munsell        0.5.0     2018-06-12 [1] CRAN (R 3.5.1)
##  nlme           3.1-137   2018-04-07 [2] CRAN (R 3.5.3)
##  nloptr         1.2.1     2018-10-03 [1] CRAN (R 3.5.1)
##  nnet           7.3-12    2016-02-02 [2] CRAN (R 3.5.3)
##  openxlsx       4.1.0.1   2019-05-28 [1] CRAN (R 3.5.3)
##  pbkrtest       0.4-7     2017-03-15 [1] CRAN (R 3.5.2)
##  pillar         1.4.2     2019-06-29 [1] CRAN (R 3.5.3)
##  pkgconfig      2.0.2     2018-08-16 [1] CRAN (R 3.5.1)
##  plogr          0.2.0     2018-03-25 [1] CRAN (R 3.5.1)
##  plyr           1.8.4     2016-06-08 [1] CRAN (R 3.5.1)
##  prettyunits    1.0.2     2015-07-13 [1] CRAN (R 3.5.1)
##  progress       1.2.2     2019-05-16 [1] CRAN (R 3.5.3)
##  promises       1.0.1     2018-04-13 [1] CRAN (R 3.5.1)
##  purrr          0.3.2     2019-03-15 [1] CRAN (R 3.5.3)
##  quantreg       5.51      2019-08-07 [1] CRAN (R 3.5.3)
##  questionr      0.7.0     2018-11-26 [1] CRAN (R 3.5.2)
##  R6             2.4.0     2019-02-14 [1] CRAN (R 3.5.2)
##  RColorBrewer   1.1-2     2014-12-07 [1] CRAN (R 3.5.0)
##  Rcpp           1.0.2     2019-07-25 [1] CRAN (R 3.5.3)
##  RcppEigen      0.3.3.5.0 2018-11-24 [1] CRAN (R 3.5.1)
##  readr        * 1.3.1     2018-12-21 [1] CRAN (R 3.5.2)
##  readxl         1.3.1     2019-03-13 [1] CRAN (R 3.5.3)
##  rematch        1.0.1     2016-04-21 [1] CRAN (R 3.5.1)
##  reshape2       1.4.3     2017-12-11 [1] CRAN (R 3.5.1)
##  rio            0.5.16    2018-11-26 [1] CRAN (R 3.5.2)
##  rlang          0.4.0     2019-06-25 [1] CRAN (R 3.5.3)
##  rstudioapi     0.10      2019-03-19 [1] CRAN (R 3.5.3)
##  scales         1.0.0     2018-08-09 [1] CRAN (R 3.5.1)
##  sf             0.7-7     2019-07-24 [1] CRAN (R 3.5.3)
##  shiny          1.3.2     2019-04-22 [1] CRAN (R 3.5.3)
##  sourcetools    0.1.7     2018-04-25 [1] CRAN (R 3.5.1)
##  sp             1.3-1     2018-06-05 [1] CRAN (R 3.5.1)
##  SparseM        1.77      2017-04-23 [1] CRAN (R 3.5.2)
##  spData         0.3.0     2019-01-07 [1] CRAN (R 3.5.2)
##  spdep          1.1-2     2019-04-05 [1] CRAN (R 3.5.3)
##  stringi        1.4.3     2019-03-12 [1] CRAN (R 3.5.3)
##  stringr        1.4.0     2019-02-10 [1] CRAN (R 3.5.2)
##  tibble       * 2.1.3     2019-06-06 [1] CRAN (R 3.5.3)
##  tidyselect     0.2.5     2018-10-11 [1] CRAN (R 3.5.1)
##  units          0.6-3     2019-05-03 [1] CRAN (R 3.5.3)
##  utf8           1.1.4     2018-05-24 [1] CRAN (R 3.5.1)
##  vctrs          0.2.0     2019-07-05 [1] CRAN (R 3.5.3)
##  viridisLite    0.3.0     2018-02-01 [1] CRAN (R 3.5.1)
##  withr          2.1.2     2018-03-15 [1] CRAN (R 3.5.1)
##  xtable         1.8-4     2019-04-21 [1] CRAN (R 3.5.3)
##  zeallot        0.1.0     2018-01-28 [1] CRAN (R 3.5.2)
##  zip            2.0.3     2019-07-03 [1] CRAN (R 3.5.3)
## 
## [1] C:/Users/Italo/Documents/R/win-library/3.5
## [2] C:/Program Files/R/R-3.5.3/library