When should I use aov() and when anova()?
Asked Answered
I

1

38

I have referred to much of online literature but it is increasing my confusion. Much of the discussion is too technical with terms unbalanced designs and I, II or III factor ANOVA and everything.

I only know that aov() uses lm() internally and is useful for data with factors. Whereas anova() can be used for different models on same dataset. Is my understanding correct?

Inculpable answered 25/11, 2016 at 23:46 Comment(4)
You are referring to R functions, & this is specific to R. You would do best to read the documentation for these functions & ask a question specific to the underlying statistical concepts.Corny
I did read the documentation the very first. With all due respect, it is the most cryptic I could find. This was my final avenue.Inculpable
To understand the requisite statistical concepts (unbalanced, type I SS, etc), it might help you to read my answer here: How to interpret type I, type II, and type III ANOVA and MANOVA?Corny
After you have read the suggested article to which @gung links why not come back here with a new question about which statistical bits you did not understand? Some of this stuff is quite tricky.Untitled
L
36

anova is substantially different from aov. Why not read R's documentation ?aov and ?anova? In short:

  • aov fits a model (as you are already aware, internally it calls lm), so it produces regression coefficients, fitted values, residuals, etc; It produces an object of primary class "aov" but also a secondary class "lm". So, it is an augmentation of an "lm" object.
  • anova is a generic function. In your scenario you are referring to anova.lm or anova.lmlist (read ?anova.lm for more info). The former analyses a fitted model (produced by lm or aov), while the latter analyses several nested (increasingly large) fitted models (by lm or aov). They both aim at producing type I (sequential) ANOVA table.

In practice, you first use lm / aov to fit a model, then use anova to analyse the result. There is nothing better than trying a small example:

fit <- aov(sr ~ ., data = LifeCycleSavings)  ## can also use `lm`
z <- anova(fit)

Now, have a look at their structure. aov returns a large object:

str(fit)

#List of 12
# $ coefficients : Named num [1:5] 28.566087 -0.461193 -1.691498 -0.000337 0.409695
#  ..- attr(*, "names")= chr [1:5] "(Intercept)" "pop15" "pop75" "dpi" ...
# $ residuals    : Named num [1:50] 0.864 0.616 2.219 -0.698 3.553 ...
#  ..- attr(*, "names")= chr [1:50] "Australia" "Austria" "Belgium" "Bolivia" ...
# $ effects      : Named num [1:50] -68.38 -14.29 7.3 -3.52 -7.94 ...
#  ..- attr(*, "names")= chr [1:50] "(Intercept)" "pop15" "pop75" "dpi" ...
# $ rank         : int 5
# $ fitted.values: Named num [1:50] 10.57 11.45 10.95 6.45 9.33 ...
#  ..- attr(*, "names")= chr [1:50] "Australia" "Austria" "Belgium" "Bolivia" ...
# $ assign       : int [1:5] 0 1 2 3 4
# $ qr           :List of 5
#  ..$ qr   : num [1:50, 1:5] -7.071 0.141 0.141 0.141 0.141 ...
#  .. ..- attr(*, "dimnames")=List of 2
#  .. .. ..$ : chr [1:50] "Australia" "Austria" "Belgium" "Bolivia" ...
#  .. .. ..$ : chr [1:5] "(Intercept)" "pop15" "pop75" "dpi" ...
#  .. ..- attr(*, "assign")= int [1:5] 0 1 2 3 4
#  ..$ qraux: num [1:5] 1.14 1.17 1.16 1.15 1.05
#  ..$ pivot: int [1:5] 1 2 3 4 5
#  ..$ tol  : num 1e-07
#  ..$ rank : int 5
#  ..- attr(*, "class")= chr "qr"
# $ df.residual  : int 45
# $ xlevels      : Named list()
# $ call         : language aov(formula = sr ~ ., data = LifeCycleSavings)
# $ terms        :Classes 'terms', 'formula'  language sr ~ pop15 + pop75 + dpi + ddpi
#  .. ..- attr(*, "variables")= language list(sr, pop15, pop75, dpi, ddpi)
#  .. ..- attr(*, "factors")= int [1:5, 1:4] 0 1 0 0 0 0 0 1 0 0 ...
#  .. .. ..- attr(*, "dimnames")=List of 2
#  .. .. .. ..$ : chr [1:5] "sr" "pop15" "pop75" "dpi" ...
#  .. .. .. ..$ : chr [1:4] "pop15" "pop75" "dpi" "ddpi"
#  .. ..- attr(*, "term.labels")= chr [1:4] "pop15" "pop75" "dpi" "ddpi"
#  .. ..- attr(*, "order")= int [1:4] 1 1 1 1
#  .. ..- attr(*, "intercept")= int 1
#  .. ..- attr(*, "response")= int 1
#  .. ..- attr(*, ".Environment")=<environment: R_GlobalEnv> 
#  .. ..- attr(*, "predvars")= language list(sr, pop15, pop75, dpi, ddpi)
#  .. ..- attr(*, "dataClasses")= Named chr [1:5] "numeric" "numeric" "numeric" "numeric" ...
#  .. .. ..- attr(*, "names")= chr [1:5] "sr" "pop15" "pop75" "dpi" ...
# $ model        :'data.frame':	50 obs. of  5 variables:
#  ..$ sr   : num [1:50] 11.43 12.07 13.17 5.75 12.88 ...
#  ..$ pop15: num [1:50] 29.4 23.3 23.8 41.9 42.2 ...
#  ..$ pop75: num [1:50] 2.87 4.41 4.43 1.67 0.83 2.85 1.34 0.67 1.06 1.14 ...
#  ..$ dpi  : num [1:50] 2330 1508 2108 189 728 ...
#  ..$ ddpi : num [1:50] 2.87 3.93 3.82 0.22 4.56 2.43 2.67 6.51 3.08 2.8 ...
#  ..- attr(*, "terms")=Classes 'terms', 'formula'  language sr ~ pop15 + pop75 + dpi + ddpi
#  .. .. ..- attr(*, "variables")= language list(sr, pop15, pop75, dpi, ddpi)
#  .. .. ..- attr(*, "factors")= int [1:5, 1:4] 0 1 0 0 0 0 0 1 0 0 ...
#  .. .. .. ..- attr(*, "dimnames")=List of 2
#  .. .. .. .. ..$ : chr [1:5] "sr" "pop15" "pop75" "dpi" ...
#  .. .. .. .. ..$ : chr [1:4] "pop15" "pop75" "dpi" "ddpi"
#  .. .. ..- attr(*, "term.labels")= chr [1:4] "pop15" "pop75" "dpi" "ddpi"
#  .. .. ..- attr(*, "order")= int [1:4] 1 1 1 1
#  .. .. ..- attr(*, "intercept")= int 1
#  .. .. ..- attr(*, "response")= int 1
#  .. .. ..- attr(*, ".Environment")=<environment: R_GlobalEnv> 
#  .. .. ..- attr(*, "predvars")= language list(sr, pop15, pop75, dpi, ddpi)
#  .. .. ..- attr(*, "dataClasses")= Named chr [1:5] "numeric" "numeric" "numeric" "numeric" ...
#  .. .. .. ..- attr(*, "names")= chr [1:5] "sr" "pop15" "pop75" "dpi" ...
# - attr(*, "class")= chr [1:2] "aov" "lm"

While anova returns:

str(z)

#Classes ‘anova’ and 'data.frame':  5 obs. of  5 variables:
# $ Df     : int  1 1 1 1 45
# $ Sum Sq : num  204.1 53.3 12.4 63.1 650.7
# $ Mean Sq: num  204.1 53.3 12.4 63.1 14.5
# $ F value: num  14.116 3.689 0.858 4.36 NA
# $ Pr(>F) : num  0.000492 0.061125 0.359355 0.042471 NA
# - attr(*, "heading")= chr  "Analysis of Variance Table\n" "Response: sr"
Luik answered 25/11, 2016 at 23:56 Comment(1)
Note that instead of calling anova(fit) you may see the usage of the summary method: summary(fit), which produces the same output (ok floating values may be rounded a little differently).Cureall

© 2022 - 2024 — McMap. All rights reserved.