Dataset
Dữ liệu được sử dụng theo ví dụ minh họa trang 78 Verma, J. P. Repeated Measures Design for Empirical Researchers, 2016 .
Bố trí thí nghiệm theo dõi tác động của việc “ngồi thiền/meditation” qua 6 tuần (biến yếu tố thời gian) đến “khả năng suy luận/reasoning ability” (biến outcome) của 10 người tham gia (biến ngẫu nhiên).
Dữ liệu có:
10 đối tượng: S1–S10
4 lần đo: week_0, week_2, week_4, week_6
Cùng một đối tượng được đo lặp lại ở cả 4 thời điểm.
library (readxl)
df <- read_excel ("data_oneway_anova_repeated.xlsx" )
df <- as.data.frame (df)
df
subject week_0 week_2 week_4 week_6
1 S1 31 36 35 37
2 S2 31 34 34 35
3 S3 32 31 37 35
4 S4 30 32 36 35
5 S5 34 33 37 37
6 S6 35 34 36 38
7 S7 36 31 31 38
8 S8 36 35 30 40
9 S9 32 31 35 36
10 S10 33 32 34 36
Lấy factor cột subject
df$ subject <- factor (df$ subject,
levels = c ("S1" , "S2" , "S3" , "S4" , "S5" ,
"S6" , "S7" , "S8" , "S9" , "S10" ))
Chuyển về dạng long
library (dplyr)
library (tidyr)
df %>% tidyr::: pivot_longer (
cols = 2 : 5 ,
names_to = "week" ,
values_to = "score"
) -> df_long
df_long <- as.data.frame (df_long)
df_long |> dplyr::: arrange (subject, week) -> df_long
df_long
subject week score
1 S1 week_0 31
2 S1 week_2 36
3 S1 week_4 35
4 S1 week_6 37
5 S2 week_0 31
6 S2 week_2 34
7 S2 week_4 34
8 S2 week_6 35
9 S3 week_0 32
10 S3 week_2 31
11 S3 week_4 37
12 S3 week_6 35
13 S4 week_0 30
14 S4 week_2 32
15 S4 week_4 36
16 S4 week_6 35
17 S5 week_0 34
18 S5 week_2 33
19 S5 week_4 37
20 S5 week_6 37
21 S6 week_0 35
22 S6 week_2 34
23 S6 week_4 36
24 S6 week_6 38
25 S7 week_0 36
26 S7 week_2 31
27 S7 week_4 31
28 S7 week_6 38
29 S8 week_0 36
30 S8 week_2 35
31 S8 week_4 30
32 S8 week_6 40
33 S9 week_0 32
34 S9 week_2 31
35 S9 week_4 35
36 S9 week_6 36
37 S10 week_0 33
38 S10 week_2 32
39 S10 week_4 34
40 S10 week_6 36
Mô tả dữ liệu
df_long |> dplyr::: group_by (week) |>
dplyr::: summarise (mean_score = mean (score),
sd_score = sd (score),
count = n ()) |> as.data.frame () -> df_sum
df_sum$ se_score <- df_sum$ sd_score / sqrt (df_sum$ count)
df_sum$ note <- "subject_mean"
df_sum
week mean_score sd_score count se_score note
1 week_0 33.0 2.160247 10 0.6831301 subject_mean
2 week_2 32.9 1.791957 10 0.5666667 subject_mean
3 week_4 34.5 2.368778 10 0.7490735 subject_mean
4 week_6 36.7 1.636392 10 0.5174725 subject_mean
library (ggplot2)
ggplot () +
geom_line (data = df_long,
mapping = aes (x = week,
y = score,
group = subject,
color = subject),
alpha = 0.2 ,
lwd = 2 ) +
geom_point (data = df_sum,
mapping = aes (x = week,
y = mean_score),
size = 3 ,
color = "blue" ) +
geom_line (data = df_sum,
mapping = aes (x = week,
y = mean_score,
group = note),
color = "blue" ,
alpha = 0.5 ,
lwd = 2 ) +
geom_errorbar (data = df_sum,
mapping = aes (x = week,
ymin = mean_score - se_score,
ymax = mean_score + se_score,
group = note),
color = "blue" ,
alpha = 0.9 ,
lwd = 1 ,
width = 0.2 ) +
guides (color = guide_legend (override.aes = list (alpha = 1 ,
lwd = 1 ))) +
theme_bw (base_size = 16 ) +
theme (axis.text = element_text (face = "bold" , color = "black" ),
axis.title = element_text (face = "bold" , color = "black" ),
legend.text = element_text (face = "bold" , color = "black" ),
legend.title = element_text (face = "bold" , color = "black" )) +
theme (legend.key.width = unit (1.5 , "cm" )) +
labs (title = "Chỉ tiêu theo dõi thay đổi theo thời gian" ,
subtitle = "Mean ± SE" ) +
geom_point (data = df_long,
mapping = aes (x = week,
y = score,
group = subject),
position = position_jitter (height = 0 ,
width = 0 ),
color = "red" ,
alpha = 0.6 )
Mở đầu
ANOVA thông thường (one-way ANOVA) là dạng thiết kế nghiên cứu để so sánh giữa các nhóm đối tượng với nhau, mỗi đối tượng chỉ đo một lần, không lặp lại (between-subjects design).
Repeated measures one-way ANOVA là dạng thiết kế nghiên cứu theo dõi cùng 1 đối tượng ở các thời điểm khác nhau (repeated measures), có đặc điểm là mỗi đối tượng tự làm nhóm đối chứng cho chính mình, loại bỏ được phần biến thiên giữa các cá nhân và chỉ kiểm định đúng sự thay đổi trong nội bộ từng người (within-subjects design).
Khi xét ở 2 thời điểm, repeated measures ANOVA và paired t-test cho kết quả giống hệt nhau, vì bản chất repeated measures ANOVA là paired t-test cho trường hợp so sánh từ 2 thời điểm trở lên.
Ưu và nhược của thiết kế này link .
Kiểm tra giả định
Tham khảo #1
Giả định về phân bố chuẩn
Mỗi tuần ta đều khảo sát trên 10 người, ta muốn đánh giá xem trung bình chỉ số “suy luận” có thay đổi theo từng tuần này không. Như vậy “week” là biến yếu tố. Ta xem xét dữ liệu ở từng tuần có tuân theo phân bố chuẩn hay không.
Dùng kiểm định Shapiro-Wilk Normality Test
library (rstatix)
df_long %>% dplyr::: group_by (week) %>% rstatix::: shapiro_test (score) |> as.data.frame ()
week variable statistic p
1 week_0 score 0.9241773 0.3931157
2 week_2 score 0.9046545 0.2462523
3 week_4 score 0.8794111 0.1284765
4 week_6 score 0.9016076 0.2281626
library (MVN)
MVN::: mvn (df[, - 1 ])
$multivariate_normality
Test Statistic p.value Method MVN
1 Henze-Zirkler 0.736 0.148 asymptotic ✓ Normal
$univariate_normality
Test Variable Statistic p.value Normality
1 Anderson-Darling week_0 0.318 0.475 ✓ Normal
2 Anderson-Darling week_2 0.389 0.313 ✓ Normal
3 Anderson-Darling week_4 0.515 0.144 ✓ Normal
4 Anderson-Darling week_6 0.392 0.307 ✓ Normal
$descriptives
Variable n Mean Std.Dev Median Min Max 25th 75th Skew Kurtosis
1 week_0 10 33.0 2.160 32.5 30 36 31.25 34.75 0.209 1.667
2 week_2 10 32.9 1.792 32.5 31 36 31.25 34.00 0.401 1.857
3 week_4 10 34.5 2.369 35.0 30 37 34.00 36.00 -0.846 2.543
4 week_6 10 36.7 1.636 36.5 35 40 35.25 37.75 0.667 2.580
$data
week_0 week_2 week_4 week_6
1 31 36 35 37
2 31 34 34 35
3 32 31 37 35
4 30 32 36 35
5 34 33 37 37
6 35 34 36 38
7 36 31 31 38
8 36 35 30 40
9 32 31 35 36
10 33 32 34 36
$subset
NULL
$outlierMethod
[1] "none"
attr(,"class")
[1] "mvn"
p-value > 0.05 là dữ liệu có phân bố chuẩn.
Dùng đồ thị QQ plot
library (ggplot2)
library (qqplotr)
ggplot (data = df_long,
mapping = aes (sample = score,
color = week,
fill = week)) +
qqplotr::: stat_qq_band (alpha = 0.2 ) +
qqplotr::: stat_qq_line () +
qqplotr::: stat_qq_point () +
facet_wrap (~ week,
scale = "free" ,
nrow = 2 ,
ncol = 2 ) +
theme_bw ()
Hầu như các điểm dữ liệu đều nằm trong vùng 95% CI của đường reference line nên dữ liệu phân bố chuẩn.
Kiểm tra outlier
library (rstatix)
df_long %>% dplyr::: group_by (week) %>% rstatix::: identify_outliers (score) |> as.data.frame ()
week subject score is.outlier is.extreme
1 week_4 S8 30 TRUE FALSE
Có 1 giá trị được xem như outlier. Ta có thể giữ lại giá trị này hoặc loại bỏ, tùy vào quyết định chuyên môn. Ở đây ta vẫn giữ lại giá trị này.