rpubs - matriz de correlacion
Mostrar correlaciones como una lista ordenada, no como una gran matriz (4)
Tengo un marco de datos con más de 100 columnas. cor () devuelve notablemente rápido, pero me dice demasiado, especialmente porque la mayoría de las columnas no están correlacionadas. Me gustaría que solo me dijera pares de columnas y su correlación, idealmente ordenada.
En caso de que no tenga 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 se ve así:
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 busco es una función que me diga:
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
Tengo una manera burda de deshacerme de algo del ruido:
z[abs(z)<0.5]=0
luego escanear buscando valores distintos de cero. Pero es muy inferior a la salida deseada arriba.
ACTUALIZACIÓN: En base a las respuestas recibidas, y algunas pruebas y errores, aquí está la solución con la que fui:
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)
Construyendo a partir de la respuesta de @ Marek. Elimina diagonales y duplicados.
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 , ]
Hay varias formas de visualizar matrices de correlación para poder obtener una imagen rápida del conjunto de datos. Aquí hay un link a un enfoque que se ve bastante bien.
Yo 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
Luego use el subset(zdf, abs(Freq) > 0.5)
para seleccionar valores significativos.
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