Просто для підбиття підсумків (і якщо гіперпосилання OP в майбутньому не вдасться), ми розглядаємо набір даних hsb2
як такий:
id female race ses schtyp prog read write math science socst
1 70 0 4 1 1 1 57 52 41 47 57
2 121 1 4 2 1 3 68 59 53 63 61
...
199 118 1 4 2 1 1 55 62 58 58 61
200 137 1 4 3 1 2 63 65 65 53 61
які можна імпортувати сюди .
Перетворюємо змінну read
в та впорядковану / порядкову змінну:
hsb2$readcat<-cut(hsb2$read, 4, ordered = TRUE)
(means = tapply(hsb2$write, hsb2$readcat, mean))
(28,40] (40,52] (52,64] (64,76]
42.77273 49.97849 56.56364 61.83333
Тепер все готово , щоб просто запустити регулярний ANOVA - так, це R, і ми в основному мають безперервну залежну змінну, write
і пояснювальну змінну з декількома рівнями, readcat
. В R ми можемо використовуватиlm(write ~ readcat, hsb2)
1. Генерування контрастної матриці:
Для упорядкованої змінної є чотири різних рівня readcat
, тому у нас буде контрасти.n - 1 = 3
table(hsb2$readcat)
(28,40] (40,52] (52,64] (64,76]
22 93 55 30
Спершу давайте підемо за гроші і подивимось на вбудовану функцію R:
contr.poly(4)
.L .Q .C
[1,] -0.6708204 0.5 -0.2236068
[2,] -0.2236068 -0.5 0.6708204
[3,] 0.2236068 -0.5 -0.6708204
[4,] 0.6708204 0.5 0.2236068
Тепер давайте розберемо, що сталося під кришкою:
scores = 1:4 # 1 2 3 4 These are the four levels of the explanatory variable.
y = scores - mean(scores) # scores - 2.5
у= [ - 1,5 , - 0,5 , 0,5 , 1,5 ]
seq_len (n) - 1 = [ 0 , 1 , 2 , 3 ]
n = 4; X <- outer(y, seq_len(n) - 1, "^") # n = 4 in this case
⎡⎣⎢⎢⎢⎢1111−1.5−0.50.51.52.250.250.252.25−3.375−0.1250.1253.375⎤⎦⎥⎥⎥⎥
Що там сталося? outer(a, b, "^")
піднімає елементи a
до елементам b
, таким чином , що перші результати стовпців з операцій, , ( - 0,5 ) 0 , 0,5 0 і 1,5 0 ; другий стовпчик з ( - 1,5 ) 1 , ( - 0,5 ) 1 , 0,5 1 і 1,5 1 ; третій з ( - 1,5 ) 2 = 2,25(−1.5)0(−0.5)00.501.50(−1.5)1(−0.5)10.511.51(−1.5)2=2.25, , 0,5 2 = 0,25 і 1,5 2 = 2,25 ; і четвертий, ( - 1,5 ) 3 = - 3,375 , ( - 0,5 ) 3 = - 0,125 , 0,5 3 = 0,125 і 1,5 3 = 3,375 .(−0.5)2=0.250.52=0.251.52=2.25(−1.5)3=−3.375(−0.5)3=−0.1250.53=0.1251.53=3.375
Далі робимо ортонормальне розкладання цієї матриці і беремо компактне подання Q ( ). Деякі внутрішні функції функцій, що використовуються в QR-факторизації в R, використані в цій публікації, далі пояснюються тут .QRc_Q = qr(X)$qr
⎡⎣⎢⎢⎢⎢−20.50.50.50−2.2360.4470.894−2.502−0.92960−4.5840−1.342⎤⎦⎥⎥⎥⎥
... з яких ми зберігаємо тільки діагональ ( z = c_Q * (row(c_Q) == col(c_Q))
). Що лежить в діагоналі: Просто "нижній" запис частини розкладу Q R. Просто? ну ні ... Виходить, що діагональ верхньої трикутної матриці містить власні значення матриці!RQR
Далі ми називаємо таку функцію:, raw = qr.qy(qr(X), z)
результат якої можна повторити "вручну" двома операціями: 1. Перетворення компактної форми , тобто в Q , перетворення, яке можна досягти за допомогою , і 2. Проведення множення матриці Q z , як і в .Qqr(X)$qr
QQ = qr.Q(qr(X))
QzQ %*% z
Принципово, що множення на власні значення R не змінює ортогональність складових векторів стовпців, але, враховуючи, що абсолютне значення власних значень з'являється у порядку зменшення вгорі зліва вниз праворуч, множення Q z буде тенденцію до зменшення значення в поліноміальних стовпцях вищого порядку:QRQz
Matrix of Eigenvalues of R
[,1] [,2] [,3] [,4]
[1,] -2 0.000000 0 0.000000
[2,] 0 -2.236068 0 0.000000
[3,] 0 0.000000 2 0.000000
[4,] 0 0.000000 0 -1.341641
Порівняйте значення в більш пізніх векторів - стовпців (квадратичної і кубічної) до і після операцій факторізаціонних і незачеплених перших двох колонках.QR
Before QR factorization operations (orthogonal col. vec.)
[,1] [,2] [,3] [,4]
[1,] 1 -1.5 2.25 -3.375
[2,] 1 -0.5 0.25 -0.125
[3,] 1 0.5 0.25 0.125
[4,] 1 1.5 2.25 3.375
After QR operations (equally orthogonal col. vec.)
[,1] [,2] [,3] [,4]
[1,] 1 -1.5 1 -0.295
[2,] 1 -0.5 -1 0.885
[3,] 1 0.5 -1 -0.885
[4,] 1 1.5 1 0.295
Нарешті ми називаємо (Z <- sweep(raw, 2L, apply(raw, 2L, function(x) sqrt(sum(x^2))), "/", check.margin = FALSE))
перетворення матриці raw
на ортонормальні вектори:
Orthonormal vectors (orthonormal basis of R^4)
[,1] [,2] [,3] [,4]
[1,] 0.5 -0.6708204 0.5 -0.2236068
[2,] 0.5 -0.2236068 -0.5 0.6708204
[3,] 0.5 0.2236068 -0.5 -0.6708204
[4,] 0.5 0.6708204 0.5 0.2236068
Ця функція просто "нормалізує" матрицю шляхом ділення ( "/"
) стовпців кожного елемента на . Таким чином, його можна розкласти в два етапи:(i), в результаті чого, це знаменники для кожного стовпця в(ii),де кожен елемент у стовпці ділиться на відповідне значення(i).∑col.x2i−−−−−−−√(i) apply(raw, 2, function(x)sqrt(sum(x^2)))
2 2.236 2 1.341
(ii)(i)
У цей момент вектори стовпців утворюють ортонормальну основу , поки ми не позбудемося першого стовпця, який буде перехопленням, і ми не відтворили результат :R4contr.poly(4)
⎡⎣⎢⎢⎢⎢−0.6708204−0.22360680.22360680.67082040.5−0.5−0.50.5−0.22360680.6708204−0.67082040.2236068⎤⎦⎥⎥⎥⎥
Стовпці цієї матриці є ортонормальними , як це можна показати (sum(Z[,3]^2))^(1/4) = 1
і z[,3]%*%z[,4] = 0
, наприклад (до речі, те саме стосується рядків). І кожен стовпець є результатом підняття початкових до 1- ї, 2- ї та 3- ї потужності відповідно - тобто лінійної, квадратичної та кубічної .scores - mean123
2. Які контрасти (стовпці) суттєво сприяють поясненню відмінностей між рівнями пояснювальної змінної?
Ми можемо просто запустити ANOVA і подивитися підсумок ...
summary(lm(write ~ readcat, hsb2))
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 52.7870 0.6339 83.268 <2e-16 ***
readcat.L 14.2587 1.4841 9.607 <2e-16 ***
readcat.Q -0.9680 1.2679 -0.764 0.446
readcat.C -0.1554 1.0062 -0.154 0.877
... щоб побачити, що існує лінійний ефект readcat
на write
, так що вихідні значення (у третьому фрагменті коду на початку публікації) можна відтворити як:
coeff = coefficients(lm(write ~ readcat, hsb2))
C = contr.poly(4)
(recovered = c(coeff %*% c(1, C[1,]),
coeff %*% c(1, C[2,]),
coeff %*% c(1, C[3,]),
coeff %*% c(1, C[4,])))
[1] 42.77273 49.97849 56.56364 61.83333
... або ...
... або набагато краще ...
Будучи ортогональних контрастів сума їх компонентів додає до нуля для через 1 , ⋯ , через т константами, а скалярний добуток будь-яких двох з них дорівнює нулю. Якби ми могли їх уявити, вони виглядали б приблизно так:∑i=1tai=0a1,⋯,at
X0,X1,⋯.Xn
Графічно це зрозуміти набагато простіше. Порівняйте фактичні засоби за групами у великих квадратних чорних блоках з передбачуваними значеннями та подивіться, чому оптимальне прямолінійне наближення з мінімальним внеском квадратичних та кубічних многочленів (з кривими, лише апроксимованими з льосом):
Якби тільки для ефекту коефіцієнти ANOVA були настільки ж великими для лінійного контрасту для інших наближень (квадратичного та кубічного), наступний безглуздий графік більш чітко зображає поліноміальні ділянки кожного "внеску":
Код тут .