2011-08-16 12 views
24

Tengo un marco de datos con más de 100 columnas. cor() vuelve notablemente rápido, pero me dice demasiado, especialmente porque la mayoría de las columnas no están correlacionadas. Me gustaría que me diga solo los pares de columnas y su correlación, idealmente ordenada.Mostrar las correlaciones como una lista ordenada, no como una matriz grande

En caso de que no tiene sentido aquí es un ejemplo artificial:

df = data.frame(a=1:10,b=20:11*20:11,c=runif(10),d=runif(10),e=runif(10)*1:10) 
z = cor(df) 

z es el siguiente:

  a   b   c   d   e 
a 1.0000000 -0.9966867 -0.38925240 -0.35142452 0.2594220 
b -0.9966867 1.0000000 0.40266637 0.35896626 -0.2859906 
c -0.3892524 0.4026664 1.00000000 0.03958307 0.1781210 
d -0.3514245 0.3589663 0.03958307 1.00000000 -0.3901608 
e 0.2594220 -0.2859906 0.17812098 -0.39016080 1.0000000 

Lo que estoy buscando es una función que en su lugar se dirá me:

a:b -0.9966867 
b:c 0.4026664 
d:e -0.39016080 
a:c -0.3892524 
b:d 0.3589663 
a:d -0.3514245 
b:e -0.2859906 
a:e 0.2594220 
c:e 0.17812098 
c:d 0.03958307 

que tienen una forma cruda para deshacerse de algunos de los ruidos:

z[abs(z)<0.5]=0 

luego escanee en busca de valores distintos de cero. Pero es muy inferior al resultado deseado anterior.

ACTUALIZACIÓN: Sobre la base de las respuestas recibidas, y un poco de ensayo y error, aquí está la solución Fui con:

z[lower.tri(z,diag=TRUE)]=NA #Prepare to drop duplicates and meaningless information 
z=as.data.frame(as.table(z)) #Turn into a 3-column table 
z=na.omit(z) #Get rid of the junk we flagged above 
z=z[order(-abs(z$Freq)),] #Sort by highest correlation (whether +ve or -ve) 
+0

¿Duplicado? http://stackoverflow.com/q/6782070/210673 – Aaron

+1

@ Aaron Sí, es exactamente la misma pregunta. ¡Mis disculpas! (Revisé la lista de Preguntas relacionadas, pero la olvidé por completo.) Pero es educativo (al menos para mí) señalar las similitudes y diferencias en las respuestas. –

Respuesta

24

siempre uso

zdf <- as.data.frame(as.table(z)) 
zdf 
# Var1 Var2  Freq 
# 1  a a 1.00000 
# 2  b a -0.99669 
# 3  c a -0.14063 
# 4  d a -0.28061 
# 5  e a 0.80519 

A continuación, utilice subset(zdf, abs(Freq) > 0.5) para seleccionar valores significativos

+2

Gracias. Todavía incluye la diagonal, incluye cada correlación dos veces y no está ordenada, pero la utilicé como punto de partida para la solución que elegí. –

7
library(reshape) 

z[z == 1] <- NA #drop perfect 
z[abs(z) < 0.5] <- NA # drop less than abs(0.5) 
z <- na.omit(melt(z)) # melt! 
z[order(-abs(z$value)),] # sort 
+0

Brillante! derretir rara vez salta a mí para ser utilizado. – nzcoops

+3

Gracias. 'z [z == 1] <- NA' es peligroso ya que también elimina las correlaciones genuinas perfectas (mejor usar' z [lower.tri (z, diag = TRUE)] = NA'). Por cierto, en este caso melt (z) hace exactamente (?) Lo mismo que as.data.frame (as.table (z)), por lo que se puede hacer sin otros paquetes. –

1

Existen varias formas de visualizar las matrices de correlación para poder obtener una imagen rápida del conjunto de datos. Aquí hay un link con un enfoque que se ve bastante bien.

+2

Gracias por la idea. Por supuesto, con más de 100 columnas se vuelve un poco práctico (excepto quizás si mis columnas estaban agrupadas de alguna manera significativa). –

2

Aprovechando la respuesta de @ Marek. Elimina la diagonal y duplica

data = as.data.frame(as.table(z)) 
combinations = combn(colnames(z) , 2 , FUN = function(x) { paste(x , collapse = "_") }) 
data = data[ data$Var1 != data$Var2 , ] 
data = data[ paste(data$Var1 , data$Var2 , sep = "_") %in% combinations , ] 
Cuestiones relacionadas