2013-08-30 15 views
10

Ho una serie di grandi dataframes che assomigliano A e B:Il calcolo della correlazione tra due datafram richiede un ciclo?

A <- data.frame(A1=c(1,2,3,4,5),B1=c(6,7,8,9,10),C1=c(11,12,13,14,15)) 

    A1 B1 C1 
1 1 6 11 
2 2 7 12 
3 3 8 13 
4 4 9 14 
5 5 10 15 

B <- data.frame(A2=c(6,7,7,10,11),B2=c(2,1,3,8,11),C2=c(1,5,16,7,8)) 

    A2 B2 C2 
1 6 2 1 
2 7 1 5 
3 7 3 16 
4 10 8 7 
5 11 11 8 

desidero creare un vettore (C) che indica la correlazione di Pearson tra A1 & A2, B1 & B2 e C1 & C2. In questo caso, ad esempio, quelle correlazioni sono:

[1] 0.95 0.92 0.46 

risposta

13

cor accetta due data.frames:

A<-data.frame(A1=c(1,2,3,4,5),B1=c(6,7,8,9,10),C1=c(11,12,13,14,15)) 

B<-data.frame(A2=c(6,7,7,10,11),B2=c(2,1,3,8,11),C2=c(1,5,16,7,8)) 

cor(A,B) 

#   A2  B2  C2 
# A1 0.9481224 0.9190183 0.459588 
# B1 0.9481224 0.9190183 0.459588 
# C1 0.9481224 0.9190183 0.459588 

diag(cor(A,B)) 
#[1] 0.9481224 0.9190183 0.4595880 

Modifica:

Ecco alcuni punti di riferimento:

Unit: microseconds 
        expr  min  lq median  uq  max neval 
     diag(cor(A, B)) 230.292 238.4225 243.0115 255.0295 352.955 100 
     mapply(cor, A, B) 267.076 281.5120 286.8030 299.5260 375.087 100 
unlist(Map(cor, A, B)) 250.053 259.1045 264.5635 275.9035 1146.140 100 

Ed it2:

E alcuni benchmark migliori usando

set.seed(42) 
A <- as.data.frame(matrix(rnorm(10*n),ncol=n)) 
B <- as.data.frame(matrix(rnorm(10*n),ncol=n)) 

enter image description here

Tuttavia, forse dovrei dire che questi parametri dipendono fortemente dal numero di righe.

Edit3: Da quando mi è stato richiesto il codice di benchmark, eccolo.

b <- sapply(2^(1:12), function(n) { 
    set.seed(42) 
    A <- as.data.frame(matrix(rnorm(10*n),ncol=n)) 
    B <- as.data.frame(matrix(rnorm(10*n),ncol=n)) 

    require(microbenchmark) 
    res <- print(microbenchmark(
        diag(cor(A,B)), 
        mapply(cor, A, B), 
        unlist(Map(cor,A,B)), 
        times=10 
       ),unit="us") 
    res$median 
}) 

b <- t(b) 

matplot(x=1:12,log10(b),type="l", 
     ylab="log10(median [µs])", 
     xlab="log2(n)",col=1:3,lty=1) 
legend("topleft", legend=c("diag(cor(A, B))", 
          "mapply(cor, A, B)", 
          "unlist(Map(cor,A,B))"),lty=1, col=1:3) 
+4

+ 'diag' per ottenere solo i valori a cui è interessato. – sgibb

+0

Grazie, stavo solo preparando la modifica. – Roland

+0

Esiste una funzione analoga a 'cor' che fornisce i valori p della correlazione? – dayne

7

È possibile utilizzare le funzioni friend of apply, Map, per quello.

Map(function(x,y) cor(x,y),A,B) 
$A1 
[1] 0.9481224 

$B1 
[1] 0.9190183 

$C1 
[1] 0.459588 

Se si desidera che l'output come vettore come suggerito dal @Jilber:

unlist(Map(function(x,y) cor(x,y),A,B)) 
     A1  B1  C1 
0.9481224 0.9190183 0.4595880 

Oppure si può semplicemente utilizzare:

unlist(Map(cor,A,B)) 
     A1  B1  C1 
0.9481224 0.9190183 0.459588 
+1

Dato che l'OP vuole un vettore, dovresti usare 'unlist (·)'. –

+0

Grazie. Lo aggiornerò. – Metrics

+0

+1 per un buon esempio di Map, non ho ancora capito bene questi concetti di programmazione funzionale in R. –

6

Un'altra alternativa è possibile utilizzare la funzione mapply

> mapply(function(x,y) cor(x,y),A,B) 
     A1  B1  C1 
0.9481224 0.9190183 0.4595880 

oppure jus t mapply(cor, A, B) come suggerito da @Aaron.

+3

Questo è quello che farei, sebbene 'mapply (cor, A, B)' sia sufficiente. – Aaron

+0

@Aaron come si può applicare questo pensiero a un elenco di file che richiedono correlazioni tra di loro? Dì A .... Z? – KennyC

+0

@KennyC: meglio penso di iniziare una nuova domanda; maggiori dettagli sarebbero necessari. – Aaron

Problemi correlati