Tengo un conjunto de datos de 17 personas, clasificando 77 declaraciones. Quiero extraer componentes principales en una matriz de correlación transpuesta de correlaciones entre personas (como variables) a través de declaraciones (como casos). Yo sé, es raro, se llama Metodología Q .
Quiero ilustrar cómo funciona PCA en este contexto, extrayendo y visualizando valores / vectores propios para solo un par de datos. (Debido a que pocas personas en mi disciplina obtienen PCA, y mucho menos su aplicación a Q, incluido yo mismo).
Quiero la visualización de este fantástico tutorial , solo para mis datos reales .
Deje que esto sea un subconjunto de mis datos:
Person1 <- c(-3,1,1,-3,0,-1,-1,0,-1,-1,3,4,5,-2,1,2,-2,-1,1,-2,1,-3,4,-6,1,-3,-4,3,3,-5,0,3,0,-3,1,-2,-1,0,-3,3,-4,-4,-7,-5,-2,-2,-1,1,1,2,0,0,2,-2,4,2,1,2,2,7,0,3,2,5,2,6,0,4,0,-2,-1,2,0,-1,-2,-4,-1)
Person2 <- c(-4,-3,4,-5,-1,-1,-2,2,1,0,3,2,3,-4,2,-1,2,-1,4,-2,6,-2,-1,-2,-1,-1,-3,5,2,-1,3,3,1,-3,1,3,-3,2,-2,4,-4,-6,-4,-7,0,-3,1,-2,0,2,-5,2,-2,-1,4,1,1,0,1,5,1,0,1,1,0,2,0,7,-2,3,-1,-2,-3,0,0,0,0)
df <- data.frame(cbind(Person1, Person2))
g <- ggplot(data = df, mapping = aes(x = Person1, y = Person2))
g <- g + geom_point(alpha = 1/3) # alpha b/c of overplotting
g <- g + geom_smooth(method = "lm") # just for comparison
g <- g + coord_fixed() # otherwise, the angles of vectors are off
g
Observe que, por medición, estos datos:
- ... tiene una media de cero,
- ... es perfectamente simétrico,
- ... y está igualmente escalado en ambas variables (no debería haber diferencia entre la correlación y la matriz de covarianza)
Ahora, quiero combinar las dos parcelas anteriores .
corre <- cor(x = df$Person1, y = df$Person2, method = "spearman") # calculate correlation, must be spearman b/c of measurement
matrix <- matrix(c(1, corre, corre, 1), nrow = 2) # make this into a matrix
eigen <- eigen(matrix) # calculate eigenvectors and values
eigen
da
> $values
> [1] 1.6 0.4
>
> $vectors
> [,1] [,2]
> [1,] 0.71 -0.71
> [2,] 0.71 0.71
>
> $vectors.scaled
> [,1] [,2]
> [1,] 0.9 -0.45
> [2,] 0.9 0.45
y, siguiendo adelante
g <- g + stat_ellipse(type = "norm")
# add ellipse, though I am not sure which is the adequate type
# as per https://github.com/hadley/ggplot2/blob/master/R/stat-ellipse.R
eigen$slopes[1] <- eigen$vectors[1,1]/eigen$vectors[2,1] # calc slopes as ratios
eigen$slopes[2] <- eigen$vectors[1,1]/eigen$vectors[1,2] # calc slopes as ratios
g <- g + geom_abline(intercept = 0, slope = eigen$slopes[1], colour = "green") # plot pc1
g <- g + geom_abline(intercept = 0, slope = eigen$slopes[2], colour = "red") # plot pc2
g <- g + geom_segment(x = 0, y = 0, xend = eigen$values[1], yend = eigen$slopes[1] * eigen$values[1], colour = "green", arrow = arrow(length = unit(0.2, "cm"))) # add arrow for pc1
g <- g + geom_segment(x = 0, y = 0, xend = eigen$values[2], yend = eigen$slopes[2] * eigen$values[2], colour = "red", arrow = arrow(length = unit(0.2, "cm"))) # add arrow for pc2
# Here come the perpendiculars, from StackExchange answer /programming/30398908/how-to-drop-a-perpendicular-line-from-each-point-in-a-scatterplot-to-an-eigenv ===
perp.segment.coord <- function(x0, y0, a=0,b=1){
#finds endpoint for a perpendicular segment from the point (x0,y0) to the line
# defined by lm.mod as y=a+b*x
x1 <- (x0+b*y0-a*b)/(1+b^2)
y1 <- a + b*x1
list(x0=x0, y0=y0, x1=x1, y1=y1)
}
ss <- perp.segment.coord(df$Person1, df$Person2, 0, eigen$slopes[1])
g <- g + geom_segment(data=as.data.frame(ss), aes(x = x0, y = y0, xend = x1, yend = y1), colour = "green", linetype = "dotted")
g
¿Este gráfico ilustra adecuadamente la extracción de vector propio / valor propio en PCA?
- No estoy seguro de cuáles serían las elipses adecuadas y / o la longitud de los vectores (¿o no importa?)
- Supongo que los vectores tienen una pendiente de
1
,-1
se debe a mis datos (clasificación? Simetría?), Y diferirían para otros datos.
Ps .: esto se basa en el tutorial anterior y esta pregunta CrossValidated .
Pps .: los perpendiculares soltados en el vector son cortesía de esta respuesta de StackExchange
fuente
1
,-1
a esperarse pendientes?Respuestas:
No hay mucho que responder aquí. Parece que has tenido algunos problemas con tu script que ya están solucionados. Actualmente no hay nada malo con su visualización y, de hecho, me parece una ilustración muy agradable y adecuada.
Para responder sus preguntas restantes:
Las pendientes de tus ejes principales siempre serán1 y - 1 para un conjunto de datos bidimensional estandarizado (es decir, si está trabajando con una matriz de correlación), como dijo @whuber en los comentarios. Vea mi respuesta aquí: ¿una matriz de correlación de dos variables siempre tiene los mismos vectores propios?
La elipse que trazaste (según mi entendimiento del código fuente de
stat_ellipse()
) es una elipse con una cobertura del 95%, suponiendo una distribución normal multivariada. Esta es una elección razonable. Tenga en cuenta que si desea una cobertura diferente, puede cambiarla a través dellevel
parámetro de entrada, pero el 95% es bastante estándar y está bien.fuente