R: Korrelation nach Gruppe berechnen

17

In R habe ich einen Datenrahmen, der eine Klassenbezeichnung C (einen Faktor) und zwei Messungen M1 und M2 umfasst . Wie berechne ich die Korrelation zwischen M1 und M2 in jeder Klasse?

Idealerweise würde ich einen Datenrahmen mit einer Zeile für jede Klasse und zwei Spalten zurückerhalten: die Klassenbezeichnung C und die Korrelation.

NPE
quelle

Antworten:

20

Das Paket plyr ist der richtige Weg.

Hier ist eine einfache Lösung:

xx <- data.frame(group = rep(1:4, 100), a = rnorm(400) , b = rnorm(400) )
head(xx)

require(plyr)
func <- function(xx)
{
return(data.frame(COR = cor(xx$a, xx$b)))
}

ddply(xx, .(group), func)

Die Ausgabe wird sein:

  group         COR
1     1  0.05152923
2     2 -0.15066838
3     3 -0.04717481
4     4  0.07899114
Tal Galili
quelle
1
(+1) Nettes plyrPaket, nicht wahr? :)
chl
Das funktioniert super. Vielen Dank für den Hinweis auf das Paket plyr! Könnten Sie bitte die Syntax ". (Group)" erläutern?
NPE
2
aix - sicher. Dies bedeutet "Teilen Sie die Daten durch die Variable zwischen. () Und führen Sie für jede Teilmenge die Funktion aus". Damit es mehr Variablen enthält, sollten Sie einfach diese Syntax verwenden:. (Var1, var2, var3). Das ist wie das Schneiden Ihrer Daten durch jede Kombination von Ebenen von var1, var2 und var3. Und bei jedem Schnitt, um Ihre Funktion auszuführen. Dieses Paket wird von Hadley (ebenfalls Autor von ggplot2) gepflegt, daher vertraue ich darauf, dass es weiterentwickelt wird.
Tal Galili
2
Übrigens, Sie könnten auch plyr mit einem parallelen Rechnen auf mehreren Kernen verwenden (fast automatisch), siehe: r-statistics.com/2010/09/…
Tal Galili
1
Das ist eine nette Antwort, aber ich bin erstaunt, dass es keine integrierte Lösung dafür gibt, so etwas wie cor (x, y, by = z) wäre so intuitiv ...
Waldir Leoncio
12

Wenn Sie dazu neigen, Funktionen im Basispaket zu verwenden, können Sie die byFunktion verwenden und dann die Daten neu zusammenstellen:

xx <- data.frame(group = rep(1:4, 100), a = rnorm(400) , b = rnorm(400) )
head(xx)

# This returns a "by" object
result <- by(xx[,2:3], xx$group, function(x) {cor(x$a, x$b)})

# You get pretty close to what you want if you coerce it into a data frame via a matrix
result.dataframe <- as.data.frame(as.matrix(result))

# Add the group column from the row names
result.dataframe$C <- rownames(result)
hgcrpd
quelle
1
Nett, danke! Ich habe damit experimentiert by, konnte aber nicht herausfinden, wie das Ergebnis in einen Datenrahmen umgewandelt werden kann.
NPE
9

Ein weiteres Beispiel mit Basispaketen und Tals Beispieldaten:

DataCov <- do.call( rbind, lapply( split(xx, xx$group),
             function(x) data.frame(group=x$group[1], mCov=cov(x$a, x$b)) ) )
Joshua Ulrich
quelle
Elegante Lösung Joshue. Denken Sie, dass es Fälle gibt, in denen eine Lösung besser ist als eine andere?
Tal Galili
2
Ich denke, es ist eine Frage der Präferenz. Mein Beispiel ist im Wesentlichen das, was es plyrtut, aber es gibt Ihnen eine feinere Kontrolle, obwohl es bei weitem nicht so sauber ist. Meine Meinung würde sich ändern, wenn eine Lösung ein besseres Zeit- / Speicherprofil hätte. Ich habe sie aber nicht verglichen.
Joshua Ulrich
Wie liefert dies die Korrelation?
2

Die Verwendung von data.table ist kürzer als dplyr

dt <- data.table(xx)
dtCor <- dt[, .(mCor = cor(M1,M2)), by=C]
jp4711
quelle
0

Hier ist eine ähnliche Methode, mit der Sie eine Tabelle mit den Werten für n und p für jede Korrelation erhalten (der Einfachheit halber auf 3 Dezimalstellen gerundet):

library(Hmisc)
corrByGroup <- function(xx){
  return(data.frame(cbind(correl = round(rcorr(xx$a, xx$b)$r[1,2], digits=3),
                          n = rcorr(xx$a, xx$b)$n[1,2],
                          pvalue = round(rcorr(xx$a, xx$b)$P[1,2], digits=3))))
}
AnnaCM
quelle
0

Hier ist eine modernere Lösung unter Verwendung des dplyrPakets (das zum Zeitpunkt der Beantwortung der Frage noch nicht vorhanden war):

Konstruieren Sie die Eingabe:

xx <- data.frame(group = rep(1:4, 100), a = rnorm(400) , b = rnorm(400) )

Berechnen Sie die Korrelationen:

library(dplyr)
xx %>%
  group_by(group) %>%
  summarize(COR=cor(a,b))

Die Ausgabe:

Source: local data frame [4 x 2]

  group         COR
  (int)       (dbl)
1     1  0.05112400
2     2  0.14203033
3     3 -0.02334135
4     4  0.10626273
Ken Williams
quelle