La pregunta se refiere a "identificar relaciones subyacentes [lineales]" entre variables.
La manera rápida y fácil de detectar relaciones es hacer retroceder cualquier otra variable (use una constante, incluso) contra esas variables usando su software favorito: cualquier buen procedimiento de regresión detectará y diagnosticará colinealidad. (Ni siquiera se molestará en mirar los resultados de la regresión: solo confiamos en un efecto secundario útil de configurar y analizar la matriz de regresión).
Sin embargo, suponiendo que se detecte la colinealidad, ¿qué sigue? El análisis de componentes principales (PCA) es exactamente lo que se necesita: sus componentes más pequeños corresponden a relaciones casi lineales. Estas relaciones se pueden leer directamente de las "cargas", que son combinaciones lineales de las variables originales. Las pequeñas cargas (es decir, las asociadas con pequeños valores propios) corresponden a casi colinealidades. Un valor propio de correspondería a una relación lineal perfecta. Valores propios ligeramente más grandes que todavía son mucho más pequeños que los más grandes corresponderían a relaciones lineales aproximadas.0 0
(Existe un arte y bastante literatura asociada con la identificación de lo que es una carga "pequeña". Para modelar una variable dependiente, sugeriría incluirla dentro de las variables independientes en el PCA para identificar los componentes, independientemente de sus tamaños, en los que la variable dependiente juega un papel importante. Desde este punto de vista, "pequeño" significa mucho más pequeño que cualquiera de esos componentes).
Veamos algunos ejemplos. (Estos se usan R
para los cálculos y el trazado). Comience con una función para realizar PCA, busque componentes pequeños, grábelos y devuelva las relaciones lineales entre ellos.
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))
}
B , C, D ,miUNA
process <- function(z, beta, sd, ...) {
x <- z %*% beta; colnames(x) <- "A"
pca(cbind(x, z + rnorm(length(x), sd=sd)), ...)
}
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 , ... , EUNA
El resultado asociado con el panel superior izquierdo fue
A B C D E
Comp.5 1 -1 -1 -1 -1
0 00 ≈ A - B - C- D - E
La salida para el panel central superior fue
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
UNA′= B′+ C′+ D′+ E′
1 , 1 / 2 , 1 / 2 , 1
En la práctica, a menudo no es el caso que una variable se destaque como una combinación obvia de las otras: todos los coeficientes pueden ser de tamaños comparables y de signos variables. Además, cuando hay más de una dimensión de las relaciones, no hay una forma única de especificarlas: se necesita un análisis adicional (como la reducción de filas) para identificar una base útil para esas relaciones. Así es como funciona el mundo: todo lo que puede decir es que estas combinaciones particulares producidas por PCA corresponden a casi ninguna variación en los datos. Para hacer frente a esto, algunas personas usan los componentes más grandes ("principales") directamente como variables independientes en la regresión o el análisis posterior, cualquiera sea la forma que pueda tomar. Si hace esto, ¡no olvide primero eliminar la variable dependiente del conjunto de variables y rehacer la PCA!
Aquí está el código para reproducir esta figura:
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")
(Tuve que jugar con el umbral en los casos de error grande para mostrar solo un componente: esa es la razón para suministrar este valor como parámetro process
).
El usuario ttnphns ha dirigido amablemente nuestra atención a un hilo estrechamente relacionado. Una de sus respuestas (por JM) sugiere el enfoque descrito aquí.