2013-08-16 9 views
20

Ho un enorme dataframe 5600 X 6592 e voglio rimuovere tutte le variabili che sono correlate tra loro più di 0.99 So come fare questo lungo, passo dopo passo, cioè formando una matrice di correlazione arrotondando i valori, rimuovendo quelli simili e utilizzando l'indicizzazione per ottenere nuovamente i miei dati "ridotti".Rimuovere le variabili altamente correlate

cor(mydata) 
mydata <- round(mydata,2) 
mydata <- mydata[,!duplicated (mydata)] 
## then do the indexing... 

Vorrei sapere se questo può essere fatto in breve comando o in qualche funzione avanzata. Sto imparando a fare uso degli strumenti potenti nella lingua R, che evita così lunghi comandi inutili

Stavo pensando a qualcosa di simile

mydata <- mydata[, which(apply(mydata, 2, function(x) !duplicated(round(cor(x),2))))] 

dispiace So che il comando precedente non funziona , ma spero di poterlo fare.

un play-dati che si applica alla domanda:

mydata <- structure(list(V1 = c(1L, 2L, 5L, 4L, 366L, 65L, 43L, 456L, 876L, 
78L, 687L, 378L, 378L, 34L, 53L, 43L), V2 = c(2L, 2L, 5L, 4L, 
366L, 65L, 43L, 456L, 876L, 78L, 687L, 378L, 378L, 34L, 53L, 
41L), V3 = c(10L, 20L, 10L, 20L, 10L, 20L, 1L, 0L, 1L, 2010L, 
20L, 10L, 10L, 10L, 10L, 10L), V4 = c(2L, 10L, 31L, 2L, 2L, 5L, 
2L, 5L, 1L, 52L, 1L, 2L, 52L, 6L, 2L, 1L), V5 = c(4L, 10L, 31L, 
2L, 2L, 5L, 2L, 5L, 1L, 52L, 1L, 2L, 52L, 6L, 2L, 3L)), .Names = c("V1", 
"V2", "V3", "V4", "V5"), class = "data.frame", row.names = c(NA, 
-16L)) 

Molte grazie

risposta

30

Sono sicuro che ci sono molti modi per farlo e certamente un po 'meglio di questo, ma questo dovrebbe funzionare. Fondamentalmente ho impostato il triangolo superiore come zero e quindi ho rimosso tutte le righe con valori superiori a 0,99.

> tmp <- cor(data) 
> tmp[upper.tri(tmp)] <- 0 
> diag(tmp) <- 0 
# Above two commands can be replaced with 
# tmp[!lower.tri(tmp)] <- 0 
# 
> 
> data.new <- data[,!apply(tmp,2,function(x) any(x > 0.99))] 
> head(data.new) 
    V2 V3 V5 
1 2 10 4 
2 2 20 10 
3 5 10 31 
4 4 20 2 
5 366 10 2 
6 65 20 5 
+0

Grazie David, fa il lavoro, anche se non so quale sia il triangolo superiore! Ho trovato la pagina di aiuto R ma non riesco a capire veramente cosa fa! :) – Error404

+0

@ Error404 'upper.tri' riempie semplicemente quella parte di una matrice con" TRUE "(e il resto è zero, ovvero FALSE), quindi' tmp [upper.tri (tmp)] 'seleziona solo la parte superiore del triangolo di 'tmp'. –

+9

Potrebbe essere più chiaro se si esegue 'data [, applica (tmp, 2, function (x) all (x <= 0.99))]' Non utilizzare nessun doppio negativo :-) –

20

Questo è il mio codice R questo sarebbe utile per voi

library('caret') 

df1 = read.csv("stack.csv") 

print (df1) 

    GA  PN  PC MBP GR AP 
1 0.033 6.652 6.681 0.194 0.874 3.177 
2 0.034 9.039 6.224 0.194 1.137 3.400 
3 0.035 10.936 10.304 1.015 0.911 4.900 
4 0.022 10.110 9.603 1.374 0.848 4.566 
5 0.035 2.963 17.156 0.599 0.823 9.406 
6 0.033 10.872 10.244 1.015 0.574 4.871 
7 0.035 21.694 22.389 1.015 0.859 9.259 
8 0.035 10.936 10.304 1.015 0.911 4.500 


df2 = cor(df1) 
hc = findCorrelation(df2, cutoff=0.3) # putt any value as a "cutoff" 
hc = sort(hc) 
reduced_Data = df1[,-c(hc)] 
print (reduced_Data) 

    GA  PN GR AP 
1 0.033 6.652 0.874 3.177 
2 0.034 9.039 1.137 3.400 
3 0.035 10.936 0.911 4.900 
4 0.022 10.110 0.848 4.566 
5 0.035 2.963 0.823 9.406 
6 0.033 10.872 0.574 4.871 
7 0.035 21.694 0.859 9.259 
8 0.035 10.936 0.911 4.500 

e di scrivere una riduzione dei dati in nuova csv basta usare:

write.csv(reduced_Data, file = "outfile.csv", row.names = FALSE) 
+0

dove hai definito findCorrelation? –

+0

@AnkitDhingra - 'findCorrelation' è una funzione integrata nel pacchetto 'caret' che jax ha caricato sulla sua prima linea –

+0

@JAX, sei un genio! Grazie – loki

6

@ David Un piccolo cambia nel tuo codice rendilo più robusto a correlazione negativa, fornendo

abs(x) > 0.99 

anziché soltanto

x > 0.99 

data.new <- data[,!apply(tmp,2,function(x) any(abs(x) > 0.99))]

applausi .. !!!