3 Jednosmjerna analiza varijance
Neka uvodna priča… 1
PDF od F-distribucije
<- expand_grid(d1 = c(1,2,5,10,15,50), d2 = c(1,2,5,10,15,50)) %>%
Fdist group_by(d1,d2) %>%
summarize(x = seq(0,5,0.01), fun = df(x, df1 = d1, df2 = d2), .groups = "drop")
%>%
Fdist ggplot(aes(x = x, y = fun)) +
geom_line(color = "blue") + ylim(0,2.5) +
ylab("df(x)") + facet_grid(vars(d1), vars(d2), labeller = label_both)

Figure 3.1: F-distribucije s različitim stupnjevima slobode
3.1 Malo matematike
Neka je \(x_{ij}\) \(j\)-to opažanje u \(i\)-toj grupi, \(\bar{x}_i\) aritmetička sredina \(i\)-te grupe i \(\bar{x}\) aritmetička sredina svih opažanja. Tada je \[x_{ij}=\bar{x}+(\bar{x}_i-\bar{x})+(x_{ij}-\bar{x}_i)\] pri čemu je \(\bar{x}_i-\bar{x}\) odstupanje aritmetičke sredine \(i\)-te grupe od aritmetičke sredine svih opažanja, a \(x_{ij}-\bar{x}_i\) odstupanje \(j\)-tog opažanja iz \(i\)-te grupe od aritmetičke sredine te grupe.
Neka je \(m\) ukupni broj grupa, a \(n_i\) broj opažanja u \(i\)-toj grupi. Varijacije unutar grupa računaju se po formuli \[SSD_W=\sum_{i=1}^{m}{\sum_{j=1}^{n_i}{(x_{ij}-\bar{x}_i)^2}},\] a varijacije između grupa po formuli \[SSD_B=\sum_{i=1}^{m}{n_i(\bar{x}_{i}-\bar{x})^2}.\]
3.2 Primjer
$dose <- factor(ToothGrowth$dose)
ToothGrowth<- aov(len ~ dose, data = ToothGrowth)
a1_model print(summary(a1_model), digits = 7)
## Df Sum Sq Mean Sq F value Pr(>F)
## dose 2 2426.434 1213.2172 67.41574 9.5327e-16 ***
## Residuals 57 1025.775 17.9961
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Ručni izračun
<- mean(ToothGrowth$len)
Ybar <- ToothGrowth %>% group_by(dose) %>%
tablica mutate(Yk = mean(len), Nk = n()) %>% ungroup()
<- tablica %>% summarize(SSB = sum((Yk - Ybar)^2)) %>% pull(SSB)
SSB <- tablica %>% summarize(SSW = sum((len - Yk)^2)) %>% pull(SSW)
SSW <- nlevels(factor(ToothGrowth$dose)) - 1
dfB <- nrow(tablica) - nlevels(factor(ToothGrowth$dose))
dfW <- SSB / dfB
MSB <- SSW / dfW
MSW <- MSB / MSW
Fvalue <- pf(Fvalue, dfB, dfW, lower.tail = FALSE)
pvalue list(SSB = SSB, SSW = SSW, dfB = dfB, dfW = dfW, MSB = MSB,
MSW = MSW, Fvalue = Fvalue, pvalue = pvalue)
## $SSB
## [1] 2426.434
##
## $SSW
## [1] 1025.775
##
## $dfB
## [1] 2
##
## $dfW
## [1] 57
##
## $MSB
## [1] 1213.217
##
## $MSW
## [1] 17.99605
##
## $Fvalue
## [1] 67.41574
##
## $pvalue
## [1] 9.532727e-16
tibble(x = seq(1,40,0.01)) %>%
ggplot(aes(x)) +
geom_text(aes(x=Fvalue, label="F", y=0.1), nudge_x = 0.9, colour="red",
text=element_text(size=11)) +
geom_area(stat = "function", fun = df, args = list(df1 = dfB, df2 = dfW), fill = "pink",
xlim = c(qf(0.95, df1 = dfB, df2 = dfW), 40), alpha=0.75) +
geom_vline(xintercept = Fvalue, linetype = "dotted") +
stat_function(fun=df, args = list(df1 = dfB, df2 = dfW), color="blue", xlim=c(1,40)) +
labs(title = "one way ANOVA")

Figure 3.2: Prihvaćamo alternativnu hipotezu da postoji značajna razlika srednjih vrijednosti po grupama
Effect size
Trebamo učitati paket lsr
.
library(lsr)
Nakon toga možemo koristiti funkciju etaSquared
.
etaSquared(x = a1_model)
## eta.sq eta.sq.part
## dose 0.7028642 0.7028642
Isti rezultat možemo dobiti i ručnim izračunom.
/ (SSB + SSW) SSB
## [1] 0.7028642
3.3 Post hoc tests
pairwise.t.test( x = ToothGrowth$len, g = ToothGrowth$dose, p.adjust.method = "none")
##
## Pairwise comparisons using t tests with pooled SD
##
## data: ToothGrowth$len and ToothGrowth$dose
##
## 0.5 1
## 1 6.7e-09 -
## 2 < 2e-16 1.4e-05
##
## P value adjustment method: none
pairwise.t.test( x = ToothGrowth$len, g = ToothGrowth$dose,
p.adjust.method = "bonferroni")
##
## Pairwise comparisons using t tests with pooled SD
##
## data: ToothGrowth$len and ToothGrowth$dose
##
## 0.5 1
## 1 2.0e-08 -
## 2 4.4e-16 4.3e-05
##
## P value adjustment method: bonferroni
pairwise.t.test( x = ToothGrowth$len, g = ToothGrowth$dose, p.adjust.method = "holm")
##
## Pairwise comparisons using t tests with pooled SD
##
## data: ToothGrowth$len and ToothGrowth$dose
##
## 0.5 1
## 1 1.3e-08 -
## 2 4.4e-16 1.4e-05
##
## P value adjustment method: holm
TukeyHSD(a1_model)
## Tukey multiple comparisons of means
## 95% family-wise confidence level
##
## Fit: aov(formula = len ~ dose, data = ToothGrowth)
##
## $dose
## diff lwr upr p adj
## 1-0.5 9.130 5.901805 12.358195 0.00e+00
## 2-0.5 15.495 12.266805 18.723195 0.00e+00
## 2-1 6.365 3.136805 9.593195 4.25e-05
3.4 Levene test
Trebamo najprije učitati paket car
.
library(car)
Nakon toga možemo koristiti funkciju leveneTest
za ispitivanje homogenosti varijanci po grupama.
leveneTest(a1_model, center = mean)
## Levene's Test for Homogeneity of Variance (center = mean)
## Df F value Pr(>F)
## group 2 0.7328 0.485
## 57
Zapravo, Levene test radi anovu na varijabli \(Z\) koja je definirana s \(z_{ik}=|x_{ik}-\bar{x}_k|\).
<- tablica %>% mutate(Zk = abs(len - Yk))
tablica1 tablica1
## # A tibble: 60 × 6
## len supp dose Yk Nk Zk
## <dbl> <fct> <fct> <dbl> <int> <dbl>
## 1 4.2 VC 0.5 10.605 20 6.405
## 2 11.5 VC 0.5 10.605 20 0.895
## 3 7.3 VC 0.5 10.605 20 3.305
## 4 5.8 VC 0.5 10.605 20 4.805
## 5 6.4 VC 0.5 10.605 20 4.205
## 6 10 VC 0.5 10.605 20 0.60500
## 7 11.2 VC 0.5 10.605 20 0.59500
## 8 11.2 VC 0.5 10.605 20 0.59500
## 9 5.2 VC 0.5 10.605 20 5.405
## 10 7 VC 0.5 10.605 20 3.605
## # … with 50 more rows
<- aov(Zk ~ dose, data = tablica1)
hom print(summary(hom), digits = 7)
## Df Sum Sq Mean Sq F value Pr(>F)
## dose 2 8.8526 4.426282 0.73277 0.48505
## Residuals 57 344.3092 6.040513
3.5 Normalnost reziduala
<- tibble(res = residuals(object = a1_model))
a1.residuals a1.residuals
## # A tibble: 60 × 1
## res
## <dbl>
## 1 -6.4050
## 2 0.89500
## 3 -3.3050
## 4 -4.805
## 5 -4.2050
## 6 -0.60500
## 7 0.59500
## 8 0.59500
## 9 -5.4050
## 10 -3.6050
## # … with 50 more rows
Histogram
ggplot(a1.residuals, aes(x=res)) + geom_histogram(binwidth=1, fill="pink", color="red")
QQ-plot
ggplot(a1.residuals, aes(sample = res)) + stat_qq() + stat_qq_line()
Shapiro-Wilk test za ispitivanje normalnosti
Početna hipoteza: “Populacija ima normalnu distribuciju.”
shapiro.test(a1.residuals$res)
##
## Shapiro-Wilk normality test
##
## data: a1.residuals$res
## W = 0.96731, p-value = 0.1076
3.6 Welchova ANOVA
Koristi se kada nije zadovoljen uvjet homogenosti varijanci grupa.
oneway.test(len ~ dose, data = ToothGrowth)
##
## One-way analysis of means (not assuming equal variances)
##
## data: len and dose
## F = 68.401, num df = 2.000, denom df = 37.743, p-value = 2.812e-13
Ako stavimo var.equal = TRUE
, dobivamo standardnu 1-ANOVU.
oneway.test(len ~ dose, data = ToothGrowth, var.equal = TRUE)
##
## One-way analysis of means
##
## data: len and dose
## F = 67.416, num df = 2, denom df = 57, p-value = 9.533e-16
Ručni izračun
<- ToothGrowth %>% group_by(dose) %>%
shap summarize(Xk = mean(len), v = var(len), n = n(), w = n / v)
<- nlevels(ToothGrowth$dose)
J <- shap %>% summarize(U = sum(w)) %>% pull(U)
U <- shap %>% summarize(Xtilda = 1 / U * sum(w * Xk)) %>% pull(Xtilda)
Xtilda <- shap %>%
A summarize(A = 1 / (J - 1) * sum(w * (Xk - Xtilda)^2)) %>%
pull(A)
<- shap %>%
B summarize(B = 2 * (J - 2) / (J^2 - 1) * sum((1 - w / U)^2 / (n - 1))) %>%
pull(B)
<- A / (1+ B)
Fw <- J - 1
v1 <- shap %>%
v2 summarize(v2 = (J^2 - 1) / (3 * sum((1 - w / U)^2 / (n - 1)))) %>%
pull(v2)
<- pf(Fw, df1=v1, df2=v2, lower.tail = FALSE)
pvalue list(tablica = shap, U = U, Xtilda = Xtilda, A = A, B = B, Fw = Fw,
df1 = v1, df2 = v2, pvalue = pvalue)
## $tablica
## # A tibble: 3 × 5
## dose Xk v n w
## <fct> <dbl> <dbl> <int> <dbl>
## 1 0.5 10.605 20.248 20 0.98776
## 2 1 19.735 19.496 20 1.0258
## 3 2 26.1 14.244 20 1.4041
##
## $U
## [1] 3.417685
##
## $Xtilda
## [1] 19.71122
##
## $A
## [1] 69.60916
##
## $B
## [1] 0.0176632
##
## $Fw
## [1] 68.40098
##
## $df1
## [1] 2
##
## $df2
## [1] 37.74325
##
## $pvalue
## [1] 2.812385e-13
3.7 Kruskal-Wallis test
Koristi se kada nije zadovoljen uvjet normalnosti.
kruskal.test(len ~ dose, data = ToothGrowth)
##
## Kruskal-Wallis rank sum test
##
## data: len by dose
## Kruskal-Wallis chi-squared = 40.669, df = 2, p-value = 1.475e-09
Ručni izračun
<- ToothGrowth %>% mutate(Rk = rank(len))
tooth.rank <- tooth.rank %>% group_by(dose) %>%
kw.tab summarize(Rkbar = mean(Rk), Nk = n()) %>% ungroup()
<- mean(tooth.rank$Rk)
Rbar <- tooth.rank %>% summarize(RSS.tot = sum((Rk - Rbar)^2)) %>% pull(RSS.tot)
RSS.tot <- kw.tab %>% summarize(RSS.b = sum(Nk * (Rkbar - Rbar)^2)) %>% pull(RSS.b)
RSS.b <- sum(kw.tab$Nk)
N <- (N - 1) * RSS.b / RSS.tot
K <- nlevels(tooth.rank$dose) - 1
dfB <- pchisq(K, dfB, lower.tail = FALSE)
pvalue list(RSS.tot = RSS.tot, RSS.b = RSS.b, dfB = dfB,
K = K, pvalue = pvalue)
## $RSS.tot
## [1] 17981
##
## $RSS.b
## [1] 12394.38
##
## $dfB
## [1] 2
##
## $K
## [1] 40.66894
##
## $pvalue
## [1] 1.475207e-09
tibble(x = seq(0,50,0.01)) %>%
ggplot(aes(x)) +
geom_text(aes(x=K, label="K", y=0.1), nudge_x = 0.9, colour="red",
text=element_text(size=11)) +
geom_area(stat = "function", fun = dchisq, args = list(df = dfB), fill = "pink",
xlim = c(qchisq(0.95, df = dfB), 40), alpha=0.75) +
geom_vline(xintercept = K, linetype = "dotted") +
stat_function(fun=dchisq, args = list(df = dfB), color="blue", xlim=c(0,50)) +
labs(title = "Kruskal-Wallis test")

Figure 3.3: Prihvaćamo alternativnu hipotezu da postoji značajna razlika srednjih vrijednosti po grupama
Dunn test (post hoc test)
Link
Dunn test
library(FSA)
dunnTest(len ~ dose, data=ToothGrowth, method="bonferroni")
## Dunn (1964) Kruskal-Wallis multiple comparison
## p-values adjusted with the Bonferroni method.
## Comparison Z P.unadj P.adj
## 1 0.5 - 1 -3.554911 3.781068e-04 1.134321e-03
## 2 0.5 - 2 -6.362612 1.983517e-10 5.950552e-10
## 3 1 - 2 -2.807701 4.989660e-03 1.496898e-02
library(dunn.test)
dunn.test(ToothGrowth$len, ToothGrowth$dose, altp = TRUE, table = FALSE, list = TRUE)
## Kruskal-Wallis rank sum test
##
## data: x and group
## Kruskal-Wallis chi-squared = 40.6689, df = 2, p-value = 0
##
##
## Comparison of x by group
## (No adjustment)
##
## List of pairwise comparisons: Z statistic (p-value)
## -----------------------------
## 0.5 - 1 : -3.554911 (0.0004)*
## 0.5 - 2 : -6.362611 (0.0000)*
## 1 - 2 : -2.807700 (0.0050)*
##
## alpha = 0.05
## Reject Ho if p <= alpha
library(dunn.test)
dunn.test(ToothGrowth$len, ToothGrowth$dose, table = FALSE, list = TRUE)
## Kruskal-Wallis rank sum test
##
## data: x and group
## Kruskal-Wallis chi-squared = 40.6689, df = 2, p-value = 0
##
##
## Comparison of x by group
## (No adjustment)
##
## List of pairwise comparisons: Z statistic (p-value)
## -----------------------------
## 0.5 - 1 : -3.554911 (0.0002)*
## 0.5 - 2 : -6.362611 (0.0000)*
## 1 - 2 : -2.807700 (0.0025)*
##
## alpha = 0.05
## Reject Ho if p <= alpha/2
samo primjer za fusnotu :)↩︎