2013-08-30 12 views
10

Mam zestaw dużych dataframes, które wyglądają jak i B:Czy obliczanie korelacji między dwiema ramkami danych wymaga pętli?

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 

ja chce utworzyć wektor (C), które oznacza korelacji Pearsona między A1 & A2, B1 & B2 i C1 & C2. W tym przypadku, na przykład, te korelacje są:

[1] 0.95 0.92 0.46 

Odpowiedz

13

cor przyjmuje dwa 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 

EDIT:

Oto kilka punktów odniesienia:

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:

I kilka lepszych wzorców korzystania

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

Należy jednak wspomnieć, że pewnie te benchmarki silnie zależy od liczby rzędów.

Edit3: Od czasu, gdy zostałem poproszony o kod testu porównawczego, oto on.

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', aby uzyskać tylko wartości, którymi jest zainteresowany. – sgibb

+0

Dzięki, właśnie przygotowywałem edycję. – Roland

+0

Czy istnieje funkcja analogiczna do "cor", która daje wartości p korelacji? – dayne

7

Można użyć do tego celu znajomego funkcji składania, Map.

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

$B1 
[1] 0.9190183 

$C1 
[1] 0.459588 

Jeśli chcesz wyjście jako wektor jak sugeruje @Jilber:

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

Albo można po prostu użyć:

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

Ponieważ OP chce wektora, powinieneś użyć 'unlist (·)'. –

+0

Dzięki. Zaktualizuję to. – Metrics

+0

+1 dla dobrego przykładu mapy, wciąż nie całkiem owinąłem głowę wokół tych koncepcji programowania funkcjonalnego w R. –

6

Inną alternatywną można użyć mapply funkcję

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

Lub s t mapply(cor, A, B) zgodnie z sugestią @Aarona.

+3

Tak właśnie zrobiłbym, chociaż "mapply (cor, A, B)" jest wystarczający. – Aaron

+0

@Aaron jak można zastosować to myślenie do listy plików wymagających korelacji między nimi? Powiedz A .... Z? – KennyC

+0

@KennyC: Lepiej myślę, aby rozpocząć nowe pytanie; potrzeba więcej szczegółów. – Aaron

Powiązane problemy