Питання задає питання про "визначення основних [лінійних] зв'язків" серед змінних.
Швидкий і простий шлях до цього виявити взаємозв'язки - це регресувати будь-яку іншу змінну (використовувати постійну, рівну) проти цих змінних за допомогою улюбленого програмного забезпечення: будь-яка хороша процедура регресії виявить і діагностує колінеарність. (Ви навіть не потрудитесь переглянути результати регресії: ми просто покладаємось на корисний побічний ефект налаштування та аналізу матриці регресії.)
Припускаючи, що виявлена колінеарність, що далі? Аналіз основних компонентів (PCA) - саме те, що потрібно: найменші його компоненти відповідають майже лінійним співвідношенням. Ці відносини можна прочитати безпосередньо з "навантажень", які є лінійними комбінаціями вихідних змінних. Невеликі навантаження (тобто пов'язані з малими власними значеннями) відповідають майже колінеарним. Власне значення 0 відповідатиме ідеальним лінійним відношенням. Трохи більші власні значення, які все ще набагато менші за найбільші, відповідали б приблизним лінійним співвідношенням.
(Існує мистецтво та досить багато літератури, пов’язаної з визначенням того, що таке "невелике" завантаження. Для моделювання залежної змінної я б запропонував включити її до складу незалежних змінних у PCA, щоб визначити компоненти - незалежно від їх розміри - у яких залежна змінна грає важливу роль. З цієї точки зору "малий" означає набагато менший, ніж будь-який такий компонент.)
Давайте розглянемо кілька прикладів. (Вони використовуються R
для обчислень та побудови графіків.) Почніть з функції виконання PCA, шукайте невеликі компоненти, будуйте їх, повертайте лінійні співвідношення між ними.
pca <- function(x, threshold, ...) {
fit <- princomp(x)
#
# Compute the relations among "small" components.
#
if(missing(threshold)) threshold <- max(fit$sdev) / ncol(x)
i <- which(fit$sdev < threshold)
relations <- fit$loadings[, i, drop=FALSE]
relations <- round(t(t(relations) / apply(relations, 2, max)), digits=2)
#
# Plot the loadings, highlighting those for the small components.
#
matplot(x, pch=1, cex=.8, col="Gray", xlab="Observation", ylab="Value", ...)
suppressWarnings(matplot(x %*% relations, pch=19, col="#e0404080", add=TRUE))
return(t(relations))
}
Застосуємо це до деяких випадкових даних. Вони засновані на чотирьох змінних (The і Е може бути і мови). Ось невелика функція для обчислення AB,C,D,EA як заданої лінійної комбінації інших. Потім він додає iid Нормально розподілених значень до всіх п'яти змінних (щоб побачити, наскільки добре працює процедура, коли мультиколінеарність лише приблизна і не точна).
process <- function(z, beta, sd, ...) {
x <- z %*% beta; colnames(x) <- "A"
pca(cbind(x, z + rnorm(length(x), sd=sd)), ...)
}
Ми готові йти: залишається лише генерувати і застосовувати ці процедури. Я використовую два сценарії, описані у запитанні: A = B + C + D + E (плюс деяка помилка у кожному) та A = B + ( C + D ) / 2 + E (плюс деяка помилка у кожному). Спершу, однак, зауважте, що PCA майже завжди застосовується до центрированних даних, тому ці імітовані дані центрируються (але не інакше змінюються масштаби) за допомогою .B,…,EA=B+C+D+EA=B+(C+D)/2+Esweep
n.obs <- 80 # Number of cases
n.vars <- 4 # Number of independent variables
set.seed(17)
z <- matrix(rnorm(n.obs*(n.vars)), ncol=n.vars)
z.mean <- apply(z, 2, mean)
z <- sweep(z, 2, z.mean)
colnames(z) <- c("B","C","D","E") # Optional; modify to match `n.vars` in length
B,…,EA
Вихід, пов'язаний з лівою верхньою панеллю, був
A B C D E
Comp.5 1 -1 -1 -1 -1
00≈A−B−C−D−E : саме того, що було вказано.
Вихід для верхньої середньої панелі був
A B C D E
Comp.5 1 -0.95 -1.03 -0.98 -1.02
(A,B,C,D,E)
A B C D E
Comp.5 1 -1.33 -0.77 -0.74 -1.07
A′=B′+C′+D′+E′
1,1/2,1/2,1
На практиці часто не так, що одна змінна виділяється як очевидна комбінація інших: всі коефіцієнти можуть бути порівнянних розмірів і різними ознаками. Більше того, коли відносин більше, ніж один вимір, не існує єдиного способу їх визначення: необхідний подальший аналіз (наприклад, зменшення рядків), щоб визначити корисну основу для цих відносин. Ось так працює світ: щоб впоратися з цим, деякі люди використовують найбільші ("головні") компоненти безпосередньо як незалежні змінні в регресії чи подальшому аналізі, в якій би формі вона не приймалася. Якщо ви це зробите, не забудьте спочатку вийняти залежну змінну з набору змінних і повторити PCA! все, що можна сказати, - це те, що ці комбінації, які виводяться за допомогою PCA, майже не змінюються в даних.
Ось код для відтворення цієї цифри:
par(mfrow=c(2,3))
beta <- c(1,1,1,1) # Also can be a matrix with `n.obs` rows: try it!
process(z, beta, sd=0, main="A=B+C+D+E; No error")
process(z, beta, sd=1/10, main="A=B+C+D+E; Small error")
process(z, beta, sd=1/3, threshold=2/3, main="A=B+C+D+E; Large error")
beta <- c(1,1/2,1/2,1)
process(z, beta, sd=0, main="A=B+(C+D)/2+E; No error")
process(z, beta, sd=1/10, main="A=B+(C+D)/2+E; Small error")
process(z, beta, sd=1/3, threshold=2/3, main="A=B+(C+D)/2+E; Large error")
(Мені довелося зіткнутися з порогом у випадках великих помилок, щоб відобразити лише один компонент: це причина для подання цього значення в якості параметра process
.)
Користувач ttnphns люб’язно скеровував нашу увагу на тісно пов'язану нитку. Одна з його відповідей (Дж. М.) пропонує підхід, описаний тут.