2013-08-30 11 views
10

Ich habe eine Reihe von großen Datenrahmen, der wie ein aussehen und B:Erfordert die Berechnung der Korrelation zwischen zwei Datenfeldern eine Schleife?

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 

Ich möchte einen Vektor (C) erzeugen, die die Pearson-Korrelation zwischen A1 & A2 bezeichnet, B1 & B2 und C1 & C2. In diesem Fall sind beispielsweise solche Korrelationen:

[1] 0.95 0.92 0.46 

Antwort

13

cor akzeptiert zwei 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:

Hier sind einige Benchmarks:

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:

Und einige bessere Benchmarks jedoch

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

verwenden, sollte ich wohl erwähnen, dass diese Benchmarks auf die Anzahl der Zeilen stark ab.

Edit3: Da ich nach dem Benchmark-Code gefragt wurde, hier ist es.

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', um nur die Werte zu erhalten, an denen er interessiert ist. – sgibb

+0

Danke, ich habe gerade den Schnitt vorbereitet. – Roland

+0

Gibt es eine Funktion analog zu "cor", die die p-Werte der Korrelation angibt? – dayne

7

Sie können mit Freund von Funktionen anwenden, Map, dafür.

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

$B1 
[1] 0.9190183 

$C1 
[1] 0.459588 

Wenn Sie die Ausgabe als Vektor wollen, wie durch @Jilber vorgeschlagen:

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

Oder Sie können einfach verwenden:

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

Da das OP einen Vektor will, sollten Sie 'unlist (·)' verwenden. –

+0

Danke. Ich werde das aktualisieren. – Metrics

+0

+1 für ein gutes Map-Beispiel, ich habe mich noch nicht ganz mit den funktionalen Programmierkonzepten von R. beschäftigt. –

6

Eine weitere Alternative Sie mapply Funktion können

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

Oder jus t mapply(cor, A, B) wie von @Aaron vorgeschlagen.

+3

Das würde ich tun, obwohl 'mapply (cor, A, B)' ausreichend ist. – Aaron

+0

@Aaron Wie könnte man dieses Denken auf eine Liste von Dateien anwenden, die Korrelationen zwischen ihnen benötigen? Sag A .... Z? – KennyC

+0

@KennyC: Besser denke ich, um eine neue Frage zu beginnen; mehr Details wären nötig. – Aaron

Verwandte Themen