R: calcular correlação por grupo


17

Em R, eu tenho um quadro de dados que compreende um rótulo de classe C (um fator) e duas medições, M1 e M2 . Como computo a correlação entre M1 e M2 em cada classe?

Idealmente, eu retornaria um quadro de dados com uma linha para cada classe e duas colunas: o rótulo da classe C e a correlação.

Respostas:


20

O pacote plyr é o caminho a percorrer.

Aqui está uma solução simples:

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)

A saída será:

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

1
(+1) plyrPacote legal , não é? :)
chl

Isso funciona muito bem. Obrigado por apontar o pacote plyr! Você poderia explicar a sintaxe ". (Group)"?
NPE

2
Aix - com certeza. Significa "dividir os dados pela variável entre. () E, em cada subconjunto, executar a função". Para incluir mais variáveis, você deve simplesmente usar esta sintaxe:. (Var1, var2, var3). O que é como cortar seus dados a cada combinação de níveis de var1, var2 e var3. E em cada corte para executar sua função. Este pacote é mantido por Hadley (também o autor do ggplot2), então eu acredito que ele continuará se desenvolvendo.
Tal Galili

2
Ah, e BTW, você também pode usar o plyr com uma computação paralela em vários núcleos (quase automaticamente), consulte: r-statistics.com/2010/09/…
Tal Galili

1
Essa é uma resposta boa, mas estou espantado não há um built-in solução para isso, algo como cor (x, y, por = z) seria tão intuitiva ...
Waldir Leoncio

12

Se você estiver inclinado a usar funções no pacote base, poderá usar a byfunção e remontar os dados:

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
Bom obrigado! Eu tenho experimentado by, mas não consegui descobrir como transformar o resultado em um quadro de dados.
NPE

9

Outro exemplo usando pacotes base e dados de exemplo de Tal:

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

Solução elegante Joshue. Você acha que há casos em que uma solução é melhor que outra?
Tal Galili

2
Eu acho que é uma questão de preferência. Meu exemplo é essencialmente o que plyrfaz, mas fornece um controle mais preciso , embora não seja tão limpo. Minha opinião mudaria se uma solução tivesse um melhor perfil de tempo / memória. Ainda não os comparei.
21910 Joshua Ulrich

Como isso retorna a correlação?

2

Usar data.table é mais curto que dplyr

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

0

Aqui está um método semelhante que fornecerá uma tabela com os valores de n e p para cada correlação (arredondado para três casas decimais por conveniência):

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

Aqui está uma solução mais moderna, usando o dplyrpacote (que ainda não existia quando a pergunta foi feita):

Construa a entrada:

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

Calcule as correlações:

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

A saída:

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
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.