R: обчислення кореляції по групі


17

У R у мене є кадр даних, що містить мітку класу C (коефіцієнт) та два вимірювання, M1 і M2 . Як обчислити кореляцію між М1 та М2 у кожному класі?

В ідеалі я б повернув кадр даних з одним рядком для кожного класу та двома стовпцями: мітка класу C та кореляція.

Відповіді:


20

Пакет Plyr - це шлях.

Ось просте рішення:

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)

Вихід буде:

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

1
(+1) Гарний plyrпакет, чи не так? :)
chl

Це чудово працює. Дякуємо, що вказали на пакет plyr! Чи можете ви поясніть, будь ласка, синтаксис ". (Group)?
NPE

2
aix - обов'язково. Це означає "розділити дані на змінну між. (), І на кожному підмножині виконувати функцію". Для того, щоб він містив більше змінних, просто слід використовувати цей синтаксис:. (Var1, var2, var3). Це як би скоротити ваші дані за кожною комбінацією рівнів var1, var2 та var3. І на кожному розрізі виконувати свою функцію. Цей пакет підтримується Хедлі (також автором ggplot2), тому я вірю, що він буде продовжувати розвиватися.
Тал Галілі

2
О, і BTW, ви також можете використовувати plyr з паралельними обчисленнями на декількох ядрах (майже автоматично), дивіться: r-statistics.com/2010/09/…
Tal Galili

1
Це гарна відповідь, але я здивований, що для цього немає вбудованого рішення, щось на зразок cor (x, y, by = z) було б таким інтуїтивно зрозумілим ...
Вальдір Леонсіо

12

Якщо ви схильні використовувати функції в базовому пакеті, ви можете використовувати byфункцію, а потім зібрати дані:

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
Приємно, дякую! Я експериментував by, але не міг зрозуміти, як перетворити результат у кадр даних.
NPE

9

Ще один приклад використання базових пакетів та приклад даних Тала:

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

Елегантне рішення Джошуе. Як ви вважаєте, чи є випадки, коли одне рішення краще, ніж інше?
Тал Галілі

2
Я думаю, що це питання переваги. Мій приклад - це, по суті, те, що plyrробить, але він дає точніший контроль, хоча це не так вже й чисто. Моя думка змінилася б, якщо одне рішення матиме кращий профіль часу та пам'яті. Я ще не порівнював їх.
Джошуа Ульріх

Як це повертає кореляцію?

2

Використання data.table коротше dplyr

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

0

Ось подібний метод, який дасть вам таблицю зі значеннями n та p для кожного співвідношення (округлений до 3 знаків після коми):

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

Ось більш сучасне рішення, використовуючи dplyr пакет (який ще не існував, коли було задано питання):

Побудувати вхід:

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

Обчисліть кореляції:

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

Вихід:

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
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.