R: compute correlation by group In R, I have a data frame comprising a class label C (a factor) and two measurements, M1 and M2. How do I compute the correlation between M1 and M2 within each class?
Ideally, I'd get back a data frame with one row for each class and two columns: the class label C and the correlation.
 A: Another example using base packages and Tal's example data:
DataCov <- do.call( rbind, lapply( split(xx, xx$group),
             function(x) data.frame(group=x$group[1], mCov=cov(x$a, x$b)) ) )

A: The package plyr is the way to go.
Here is a simple solution:
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)

The output will be:
  group         COR
1     1  0.05152923
2     2 -0.15066838
3     3 -0.04717481
4     4  0.07899114

A: Using data.table is shorter than dplyr
dt <- data.table(xx)
dtCor <- dt[, .(mCor = cor(M1,M2)), by=C]

A: If you are inclined to use functions in the base package, you can use the by function, then reassemble the data:
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)

A: Here's a similar method that will give you a table with the n's and p values for each correlation as well (rounded to 3 decimal places for convenience):
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))))
}

A: Here's a more modern solution, using the dplyr package (which didn't yet exist when the question was asked):
Construct the input:
xx <- data.frame(group = rep(1:4, 100), a = rnorm(400) , b = rnorm(400) )

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

The output:
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

