R: calcola la correlazione per gruppo


17

In R, ho un frame di dati comprendente un'etichetta di classe C (un fattore) e due misurazioni, M1 e M2 . Come calcolo la correlazione tra M1 e M2 all'interno di ogni classe?

Idealmente, vorrei recuperare un frame di dati con una riga per ogni classe e due colonne: l'etichetta della classe C e la correlazione.

Risposte:


20

Il pacchetto plyr è la strada da percorrere.

Ecco una soluzione semplice:

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)

L'output sarà:

  group         COR
1     1  0.05152923
2     2 -0.15066838
3     3 -0.04717481
4     4  0.07899114

1
(+1) Bel plyrpacchetto, vero? :)
chl

Funziona benissimo. Grazie per aver sottolineato il pacchetto plyr! Potresti spiegare la sintassi ". (Gruppo)"?
NPE,

2
aix - certo. Significa "dividere i dati per la variabile tra. () E su ogni sottoinsieme eseguire la funzione". Per includere più variabili, è sufficiente utilizzare questa sintassi:. (Var1, var2, var3). È come tagliare i dati per ogni combinazione di livelli di var1, var2 e var3. E su ogni taglio per svolgere la tua funzione. Questo pacchetto è gestito da Hadley (anche l'autore di ggplot2), quindi confido che continuerà a svilupparsi.
Tal Galili,

2
Oh, e BTW, potresti anche usare plyr con un calcolo parallelo su più core (quasi automaticamente), vedi: r-statistics.com/2010/09/…
Tal Galili,

1
Questa è una bella risposta, ma sono sorpreso che non ci sia una soluzione integrata per questo, qualcosa come cor (x, y, by = z) sarebbe così intuitivo ...
Waldir Leoncio

12

Se si è inclini a utilizzare le funzioni nel pacchetto di base, è possibile utilizzare la byfunzione, quindi riassemblare i dati:

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)

1
Bene grazie! Ho sperimentato by, ma non sono riuscito a capire come trasformare il risultato in un frame di dati.
NPE,

9

Un altro esempio che utilizza i pacchetti di base e i dati di esempio di Tal:

DataCov <- do.call( rbind, lapply( split(xx, xx$group),
             function(x) data.frame(group=x$group[1], mCov=cov(x$a, x$b)) ) )

Soluzione elegante Joshue. Pensi che ci siano casi in cui una soluzione è migliore di un'altra?
Tal Galili,

2
Penso che sia una questione di preferenza. Il mio esempio è essenzialmente quello che plyrfa ma ti dà un controllo più preciso, anche se non è altrettanto pulito. La mia opinione cambierebbe se una soluzione avesse un profilo tempo / memoria migliore. Non li ho confrontati però.
Joshua Ulrich,

In che modo questo restituisce la correlazione?

2

L'uso di data.table è più breve di dplyr

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

0

Ecco un metodo simile che ti darà una tabella con i valori di n e p anche per ogni correlazione (arrotondato al terzo decimale per comodità):

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))))
}

0

Ecco una soluzione più moderna, usando il dplyrpacchetto (che non esisteva ancora al momento della domanda):

Costruire l'input:

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

Calcola le correlazioni:

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

Il risultato:

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
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.