Напомним (и в случае, если гиперссылки 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
Y= [ - 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 ,( - 1,5 )0( - 0,5 )00,501,50( - 1,5 )1 , 0,5 1 и 1,5 1 ; третье из ( - 1,5 ) 2 = 2,25( - 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
"/"
∑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
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
... или...
... или намного лучше ...
∑i=1tai=0a1,⋯,at
X0,X1,⋯.Xn
Графически это гораздо проще понять. Сравните фактические средние значения по группам в больших квадратных черных блоках с предсказанными значениями и посмотрите, почему оптимально приближение прямой линии с минимальным вкладом квадратичных и кубических полиномов (с кривыми, аппроксимированными только с лессом):
Если бы просто для эффекта коэффициенты ANOVA были такими же большими для линейного контраста для других приближений (квадратичного и кубического), то бессмысленный график, приведенный ниже, более четко отображал бы полиномиальные графики каждого «вклада»:
Код здесь .