Câu trả lời trực tiếp cho câu hỏi của bạn là mô hình cuối cùng bạn đã viết,
anova(lmer(y ~ a*b*c +(1|subject) + (1|a:subject) + (1|b:subject) + (1|c:subject) +
(1|a:b:subject) + (1|a:c:subject) + (1|b:c:subject), d))
Tôi tin là "về nguyên tắc" chính xác, mặc dù đó là một tham số lạ mà dường như không phải lúc nào cũng hoạt động tốt trong thực tế.
Về lý do tại sao đầu ra mà bạn nhận được từ mô hình này không nhất quán với aov()
đầu ra, tôi nghĩ có hai lý do.
- Tập dữ liệu mô phỏng đơn giản của bạn là bệnh lý trong đó mô hình phù hợp nhất là mô hình ngụ ý các thành phần phương sai âm, mô hình hỗn hợp phù hợp với
lmer()
(và hầu hết các chương trình mô hình hỗn hợp khác) sẽ không cho phép.
- Ngay cả với một bộ dữ liệu không bệnh lý, cách bạn thiết lập mô hình, như đã đề cập ở trên, dường như không phải lúc nào cũng hoạt động tốt trong thực tế, mặc dù tôi phải thừa nhận rằng tôi không thực sự hiểu tại sao. Theo tôi thì nó cũng lạ, nhưng đó là một câu chuyện khác.
Trước tiên hãy để tôi chứng minh tham số hóa mà tôi thích trên ví dụ ANOVA hai chiều ban đầu của bạn. Giả sử rằng tập dữ liệu của bạn đã d
được tải. Mô hình của bạn (lưu ý rằng tôi đã thay đổi từ mã giả sang mã tương phản) là:
options(contrasts=c("contr.sum","contr.poly"))
mod1 <- lmer(y ~ a*b+(1|subject) + (1|a:subject) + (1|b:subject),
data = d[d$c == "1",])
anova(mod1)
# Analysis of Variance Table
# Df Sum Sq Mean Sq F value
# a 1 2.20496 2.20496 3.9592
# b 1 0.13979 0.13979 0.2510
# a:b 1 1.23501 1.23501 2.2176
mà làm việc tốt ở đây là nó phù hợp với aov()
đầu ra. Mô hình mà tôi thích bao gồm hai thay đổi: mã hóa tương phản thủ công các yếu tố để chúng tôi không làm việc với các đối tượng yếu tố R (mà tôi khuyên bạn nên thực hiện trong 100% trường hợp) và chỉ định các hiệu ứng ngẫu nhiên khác nhau:
d <- within(d, {
A <- 2*as.numeric(paste(a)) - 3
B <- 2*as.numeric(paste(b)) - 3
C <- 2*as.numeric(paste(c)) - 3
})
mod2 <- lmer(y ~ A*B + (1|subject)+(0+A|subject)+(0+B|subject),
data = d[d$c == "1",])
anova(mod2)
# Analysis of Variance Table
# Df Sum Sq Mean Sq F value
# A 1 2.20496 2.20496 3.9592
# B 1 0.13979 0.13979 0.2510
# A:B 1 1.23501 1.23501 2.2176
logLik(mod1)
# 'log Lik.' -63.53034 (df=8)
logLik(mod2)
# 'log Lik.' -63.53034 (df=8)
Hai cách tiếp cận hoàn toàn tương đương trong bài toán 2 chiều đơn giản. Bây giờ chúng ta sẽ chuyển sang vấn đề 3 chiều. Tôi đã đề cập trước đó rằng tập dữ liệu mẫu bạn đưa ra là bệnh lý. Vì vậy, điều tôi muốn làm trước khi giải quyết tập dữ liệu mẫu của bạn là trước tiên tạo một tập dữ liệu từ mô hình thành phần phương sai thực tế (nghĩa là, nơi các thành phần phương sai khác không được xây dựng trong mô hình thực). Đầu tiên tôi sẽ chỉ ra cách tham số ưa thích của tôi dường như hoạt động tốt hơn so với tham số bạn đề xuất. Sau đó, tôi sẽ trình bày một cách khác để ước tính các thành phần phương sai không áp đặt rằng chúng phải không âm. Sau đó, chúng tôi sẽ ở một vị trí để xem vấn đề với bộ dữ liệu mẫu ban đầu.
Bộ dữ liệu mới sẽ có cấu trúc giống hệt nhau ngoại trừ chúng tôi sẽ có 50 đối tượng:
set.seed(9852903)
d2 <- expand.grid(A=c(-1,1), B=c(-1,1), C=c(-1,1), sub=seq(50))
d2 <- merge(d2, data.frame(sub=seq(50), int=rnorm(50), Ab=rnorm(50),
Bb=rnorm(50), Cb=rnorm(50), ABb=rnorm(50), ACb=rnorm(50), BCb=rnorm(50)))
d2 <- within(d2, {
y <- int + (1+Ab)*A + (1+Bb)*B + (1+Cb)*C + (1+ABb)*A*B +
(1+ACb)*A*C + (1+BCb)*B*C + A*B*C + rnorm(50*2^3)
a <- factor(A)
b <- factor(B)
c <- factor(C)
})
Các tỷ lệ F mà chúng tôi muốn khớp là:
aovMod1 <- aov(y ~ a*b*c + Error(factor(sub)/(a*b*c)), data = d2)
tab <- lapply(summary(aovMod1), function(x) x[[1]][1,2:4])
do.call(rbind, tab)
# Sum Sq Mean Sq F value
# Error: factor(sub) 439.48 8.97
# Error: factor(sub):a 429.64 429.64 32.975
# Error: factor(sub):b 329.48 329.48 27.653
# Error: factor(sub):c 165.44 165.44 17.924
# Error: factor(sub):a:b 491.33 491.33 49.694
# Error: factor(sub):a:c 305.46 305.46 41.703
# Error: factor(sub):b:c 466.09 466.09 40.655
# Error: factor(sub):a:b:c 392.76 392.76 448.101
Dưới đây là hai mô hình của chúng tôi:
mod3 <- lmer(y ~ a*b*c + (1|sub)+(1|a:sub)+(1|b:sub)+(1|c:sub)+
(1|a:b:sub)+(1|a:c:sub)+(1|b:c:sub), data = d2)
anova(mod3)
# Analysis of Variance Table
# Df Sum Sq Mean Sq F value
# a 1 32.73 32.73 34.278
# b 1 21.68 21.68 22.704
# c 1 12.53 12.53 13.128
# a:b 1 60.93 60.93 63.814
# a:c 1 50.38 50.38 52.762
# b:c 1 57.30 57.30 60.009
# a:b:c 1 392.76 392.76 411.365
mod4 <- lmer(y ~ A*B*C + (1|sub)+(0+A|sub)+(0+B|sub)+(0+C|sub)+
(0+A:B|sub)+(0+A:C|sub)+(0+B:C|sub), data = d2)
anova(mod4)
# Analysis of Variance Table
# Df Sum Sq Mean Sq F value
# A 1 28.90 28.90 32.975
# B 1 24.24 24.24 27.653
# C 1 15.71 15.71 17.924
# A:B 1 43.56 43.56 49.694
# A:C 1 36.55 36.55 41.703
# B:C 1 35.63 35.63 40.655
# A:B:C 1 392.76 392.76 448.101
logLik(mod3)
# 'log Lik.' -984.4531 (df=16)
logLik(mod4)
# 'log Lik.' -973.4428 (df=16)
Như chúng ta có thể thấy, chỉ có phương thức thứ hai khớp với đầu ra từ aov()
, mặc dù phương thức đầu tiên ít nhất là trong sân bóng. Phương pháp thứ hai cũng đạt được khả năng đăng nhập cao hơn. Tôi không chắc tại sao hai phương pháp này cho kết quả khác nhau, vì một lần nữa tôi nghĩ rằng chúng tương đương "về nguyên tắc", nhưng có lẽ đó là vì một số lý do số / tính toán. Hoặc có thể tôi nhầm và chúng không tương đương ngay cả về nguyên tắc.
Bây giờ tôi sẽ chỉ ra một cách khác để ước tính các thành phần phương sai dựa trên các ý tưởng ANOVA truyền thống. Về cơ bản, chúng tôi sẽ lấy các phương trình bình phương trung bình dự kiến cho thiết kế của bạn, thay thế các giá trị quan sát của bình phương trung bình và giải các thành phần phương sai. Để có được bình phương trung bình dự kiến, chúng ta sẽ sử dụng hàm R mà tôi đã viết cách đây vài năm, được gọi EMS()
là tài liệu TẠI ĐÂY . Dưới đây tôi giả sử chức năng đã được tải.
# prepare coefficient matrix
r <- 1 # number of replicates
s <- 50 # number of subjects
a <- 2 # number of levels of A
b <- 2 # number of levels of B
c <- 2 # number of levels of C
CT <- EMS(r ~ a*b*c*s, random="s")
expr <- strsplit(CT[CT != ""], split="")
expr <- unlist(lapply(expr, paste, collapse="*"))
expr <- sapply(expr, function(x) eval(parse(text=x)))
CT[CT != ""] <- expr
CT[CT == ""] <- 0
mode(CT) <- "numeric"
# residual variance and A*B*C*S variance are confounded in
# this design, so remove the A*B*C*S variance component
CT <- CT[-15,-2]
CT
# VarianceComponent
# Effect e b:c:s a:c:s a:b:s a:b:c c:s b:s a:s b:c a:c a:b s c b a
# a 1 0 0 0 0 0 0 4 0 0 0 0 0 0 200
# b 1 0 0 0 0 0 4 0 0 0 0 0 0 200 0
# c 1 0 0 0 0 4 0 0 0 0 0 0 200 0 0
# s 1 0 0 0 0 0 0 0 0 0 0 8 0 0 0
# a:b 1 0 0 2 0 0 0 0 0 0 100 0 0 0 0
# a:c 1 0 2 0 0 0 0 0 0 100 0 0 0 0 0
# b:c 1 2 0 0 0 0 0 0 100 0 0 0 0 0 0
# a:s 1 0 0 0 0 0 0 4 0 0 0 0 0 0 0
# b:s 1 0 0 0 0 0 4 0 0 0 0 0 0 0 0
# c:s 1 0 0 0 0 4 0 0 0 0 0 0 0 0 0
# a:b:c 1 0 0 0 50 0 0 0 0 0 0 0 0 0 0
# a:b:s 1 0 0 2 0 0 0 0 0 0 0 0 0 0 0
# a:c:s 1 0 2 0 0 0 0 0 0 0 0 0 0 0 0
# b:c:s 1 2 0 0 0 0 0 0 0 0 0 0 0 0 0
# e 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0
# get mean squares
(MSmod <- summary(aov(y ~ a*b*c*factor(sub), data=d2)))
# Df Sum Sq Mean Sq
# a 1 429.6 429.6
# b 1 329.5 329.5
# c 1 165.4 165.4
# factor(sub) 49 439.5 9.0
# a:b 1 491.3 491.3
# a:c 1 305.5 305.5
# b:c 1 466.1 466.1
# a:factor(sub) 49 638.4 13.0
# b:factor(sub) 49 583.8 11.9
# c:factor(sub) 49 452.2 9.2
# a:b:c 1 392.8 392.8
# a:b:factor(sub) 49 484.5 9.9
# a:c:factor(sub) 49 358.9 7.3
# b:c:factor(sub) 49 561.8 11.5
# a:b:c:factor(sub) 49 42.9 0.9
MS <- MSmod[[1]][,"Mean Sq"]
# solve
ans <- solve(CT, MS)
cbind(rev(ans[c(grep("e",names(ans)),grep("s",names(ans)))])/
c(1,2,2,2,4,4,4,1))
# s 1.0115549
# a:s 1.5191114
# b:s 1.3797937
# c:s 1.0441351
# a:b:s 1.1263331
# a:c:s 0.8060402
# b:c:s 1.3235126
# e 0.8765093
summary(mod4)
# Random effects:
# Groups Name Variance Std.Dev.
# sub (Intercept) 1.0116 1.0058
# sub.1 A 1.5191 1.2325
# sub.2 B 1.3798 1.1746
# sub.3 C 1.0441 1.0218
# sub.4 A:B 1.1263 1.0613
# sub.5 A:C 0.8060 0.8978
# sub.6 B:C 1.3235 1.1504
# Residual 0.8765 0.9362
# Number of obs: 400, groups: sub, 50
Được rồi, bây giờ chúng ta sẽ trở lại ví dụ ban đầu. Các tỷ lệ F mà chúng tôi đang cố gắng khớp là:
aovMod2 <- aov(y~a*b*c+Error(subject/(a*b*c)), data = d)
tab <- lapply(summary(aovMod2), function(x) x[[1]][1,2:4])
do.call(rbind, tab)
# Sum Sq Mean Sq F value
# Error: subject 13.4747 1.2250
# Error: subject:a 1.4085 1.4085 1.2218
# Error: subject:b 3.1180 3.1180 5.5487
# Error: subject:c 6.3809 6.3809 5.2430
# Error: subject:a:b 1.5706 1.5706 2.6638
# Error: subject:a:c 1.0907 1.0907 1.5687
# Error: subject:b:c 1.4128 1.4128 2.3504
# Error: subject:a:b:c 0.1014 0.1014 0.1149
Dưới đây là hai mô hình của chúng tôi:
mod5 <- lmer(y ~ a*b*c + (1|subject)+(1|a:subject)+(1|b:subject)+
(1|c:subject)+(1|a:b:subject)+(1|a:c:subject)+(1|b:c:subject),
data = d)
anova(mod5)
# Analysis of Variance Table
# Df Sum Sq Mean Sq F value
# a 1 0.8830 0.8830 1.3405
# b 1 3.1180 3.1180 4.7334
# c 1 3.8062 3.8062 5.7781
# a:b 1 1.5706 1.5706 2.3844
# a:c 1 0.9620 0.9620 1.4604
# b:c 1 1.4128 1.4128 2.1447
# a:b:c 1 0.1014 0.1014 0.1539
mod6 <- lmer(y ~ A*B*C + (1|subject)+(0+A|subject)+(0+B|subject)+
(0+C|subject)+(0+A:B|subject)+(0+A:C|subject)+
(0+B:C|subject), data = d)
anova(mod6)
# Analysis of Variance Table
# Df Sum Sq Mean Sq F value
# a 1 0.8830 0.8830 1.3405
# b 1 3.1180 3.1180 4.7334
# c 1 3.8062 3.8062 5.7781
# a:b 1 1.5706 1.5706 2.3844
# a:c 1 0.9620 0.9620 1.4604
# b:c 1 1.4128 1.4128 2.1447
# a:b:c 1 0.1014 0.1014 0.1539
logLik(mod5)
# 'log Lik.' -135.0351 (df=16)
logLik(mod6)
# 'log Lik.' -134.9191 (df=16)
Trong trường hợp này, hai mô hình mang lại kết quả cơ bản giống nhau, mặc dù phương pháp thứ hai có khả năng đăng nhập cao hơn một chút. Không phương pháp nào phù hợp aov()
. Nhưng hãy xem những gì chúng ta nhận được khi giải quyết các thành phần phương sai như chúng ta đã làm ở trên, sử dụng quy trình ANOVA không ràng buộc các thành phần phương sai là không âm (nhưng chỉ có thể được sử dụng trong các thiết kế cân bằng không có dự đoán liên tục và không có thiếu dữ liệu; các giả định ANOVA cổ điển).
# prepare coefficient matrix
r <- 1 # number of replicates
s <- 12 # number of subjects
a <- 2 # number of levels of A
b <- 2 # number of levels of B
c <- 2 # number of levels of C
CT <- EMS(r ~ a*b*c*s, random="s")
expr <- strsplit(CT[CT != ""], split="")
expr <- unlist(lapply(expr, paste, collapse="*"))
expr <- sapply(expr, function(x) eval(parse(text=x)))
CT[CT != ""] <- expr
CT[CT == ""] <- 0
mode(CT) <- "numeric"
# residual variance and A*B*C*S variance are confounded in
# this design, so remove the A*B*C*S variance component
CT <- CT[-15,-2]
# get mean squares
MSmod <- summary(aov(y ~ a*b*c*subject, data=d))
MS <- MSmod[[1]][,"Mean Sq"]
# solve
ans <- solve(CT, MS)
cbind(rev(ans[c(grep("e",names(ans)),grep("s",names(ans)))])/
c(1,2,2,2,4,4,4,1))
# s 0.04284033
# a:s 0.03381648
# b:s -0.04004005
# c:s 0.04184887
# a:b:s -0.03657940
# a:c:s -0.02337501
# b:c:s -0.03514457
# e 0.88224787
summary(mod6)
# Random effects:
# Groups Name Variance Std.Dev.
# subject (Intercept) 7.078e-02 2.660e-01
# subject.1 A 6.176e-02 2.485e-01
# subject.2 B 0.000e+00 0.000e+00
# subject.3 C 6.979e-02 2.642e-01
# subject.4 A:B 1.549e-16 1.245e-08
# subject.5 A:C 4.566e-03 6.757e-02
# subject.6 B:C 0.000e+00 0.000e+00
# Residual 6.587e-01 8.116e-01
# Number of obs: 96, groups: subject, 12
Bây giờ chúng ta có thể thấy những gì là bệnh lý về ví dụ ban đầu. Mô hình phù hợp nhất là mô hình ngụ ý rằng một số thành phần phương sai ngẫu nhiên là âm. Nhưng lmer()
(và hầu hết các chương trình mô hình hỗn hợp khác) ràng buộc các ước tính của các thành phần phương sai là không âm. Điều này thường được coi là một hạn chế hợp lý, vì phương sai tất nhiên có thể không bao giờ thực sự là tiêu cực. Tuy nhiên, hậu quả của hạn chế này là các mô hình hỗn hợp không thể biểu diễn chính xác các bộ dữ liệu có tương quan nội hàm âm, nghĩa là các bộ dữ liệu trong đó các quan sát từ cùng một cụm ít hơn(chứ không phải nhiều hơn) tương tự trung bình so với các quan sát được rút ngẫu nhiên từ tập dữ liệu và do đó, phương sai trong cụm vượt quá đáng kể giữa phương sai giữa cụm. Các bộ dữ liệu này là các bộ dữ liệu hoàn toàn hợp lý mà đôi khi người ta sẽ bắt gặp trong thế giới thực (hoặc vô tình mô phỏng!), Nhưng chúng không thể được mô tả hợp lý bởi mô hình thành phần phương sai, bởi vì chúng ngụ ý các thành phần phương sai âm. Tuy nhiên, chúng có thể được mô tả "không hợp lý" bởi các mô hình như vậy, nếu phần mềm sẽ cho phép nó. aov()
cho phép nó lmer()
không làm.
y ~ a*b + (1 + a*b|subject), d[d$c == "1",]
không? Hoặc có lẽ tôi đang thiếu một cái gì đó?