Корреляция между группами в данных Р.таблица
есть ли способ элегантно вычислить корреляции между значениями, если эти значения хранятся группой в одном столбце данных.таблица (кроме преобразования данных.таблица к матрице)?
library(data.table)
set.seed(1) # reproducibility
dt <- data.table(id=1:4, group=rep(letters[1:2], c(4,4)), value=rnorm(8))
setkey(dt, group)
# id group value
# 1: 1 a -0.6264538
# 2: 2 a 0.1836433
# 3: 3 a -0.8356286
# 4: 4 a 1.5952808
# 5: 1 b 0.3295078
# 6: 2 b -0.8204684
# 7: 3 b 0.4874291
# 8: 4 b 0.7383247
что-то, что работает, но требует имен групп в качестве входных данных:
cor(dt["a"]$value, dt["b"]$value)
# [1] 0.1556371
Я больше ищу что-то вроде:
dt[, cor(value, value), by="group"]
но это не дает мне связь(с) я после.
вот та же проблема в матрице с правильными результатами.
set.seed(1) # reproducibility
m <- matrix(rnorm(8), ncol=2)
dimnames(m) <- list(id=1:4, group=letters[1:2])
# group
# id a b
# 1 -0.6264538 0.3295078
# 2 0.1836433 -0.8204684
# 3 -0.8356286 0.4874291
# 4 1.5952808 0.7383247
cor(m) # correlations between groups
# a b
# a 1.0000000 0.1556371
# b 0.1556371 1.0000000
любые комментарии или помощь очень ценятся.
3 ответов
нет простого способа сделать это с data.table
. Первый способ, который вы предоставили:
cor(dt["a"]$value, dt["b"]$value)
- вероятно, самый простой.
альтернативой является reshape
код data.table
С до :
> dtw <- reshape(dt, timevar="group", idvar="id", direction="wide")
> dtw
id value.a value.b
1: 1 -0.6264538 0.3295078
2: 2 0.1836433 -0.8204684
3: 3 -0.8356286 0.4874291
4: 4 1.5952808 0.7383247
> cor(dtw[,list(value.a, value.b)])
value.a value.b
value.a 1.0000000 0.1556371
value.b 0.1556371 1.0000000
обновление: если вы используете data.table
версии >= 1.9.0, то вы можете использовать dcast.data.table
вместо этого, что будет намного быстрее. Проверка этот пост для получения дополнительной информации.
dcast.data.table(dt, id ~ group)
Я не знаю, как получить его в матричной форме сразу, но я нахожу это решение полезным:
dt[, {x = value; dt[, cor(x, value), by = group]}, by=group]
group group V1
1: a a 1.0000000
2: a b 0.1556371
3: b a 0.1556371
4: b b 1.0000000
так как вы начали с расплавленного набора данных, и вы в конечном итоге с расплавленным представлением корреляции.
используя эту форму, вы также можете просто рассчитать определенные пары,в частности, это пустая трата времени на расчет обеих диагоналей. Например:
dt[, {x = value; g = group; dt[group <= g, list(cor(x, value)), by = group]}, by=group]
group group V1
1: a a 1.0000000
2: b a 0.1556371
3: b b 1.0000000
кроме того, эта форма работает так же хорошо для кросс-корреляции между двумя наборами (т. е. блоком по диагонали)
library(data.table)
set.seed(1) # reproducibility
dt1 <- data.table(id=1:4, group=rep(letters[1:2], c(4,4)), value=rnorm(8))
dt2 <- data.table(id=1:4, group=rep(letters[3:4], c(4,4)), value=rnorm(8))
setkey(dt1, group)
setkey(dt2, group)
dt1[, {x = value; g = group; dt2[, list(cor(x, value)), by = group]}, by=group]
group group V1
1: a c -0.39499814
2: a d 0.74234458
3: b c 0.96088312
4: b d 0.08016723
очевидно, что если вы в конечном итоге хотите их в матричной форме, то вы можете использовать dcast
или dcast.data.table
, однако, обратите внимание, что в приведенных выше примерах у вас есть два столбца с одинаковым именем, чтобы исправить это, стоит переименовать их в функцию j. Для исходной задачи:
dcast.data.table(dt[, {x = value; g1=group; dt[, list(g1, g2=group, c =cor(x, value)), by = group]}, by=group], g1~g2, value.var = "c")
g1 a b
1: a 1.0000000 0.1556371
2: b 0.1556371 1.0000000
С тех пор я нашел даже простую альтернативу для этого. Вы были на самом деле довольно близки с вашим dt[, cor(value, value), by="group"]
подход. На самом деле вам нужно сначала сделать Декартовое соединение по датам, а затем сгруппировать по.
Т. е.
dt[dt, allow.cartesian=T][, cor(value, value), by=list(group, group.1)]
это имеет то преимущество, что он будет присоединяться к серии вместе (а не предполагать, что они имеют одинаковую длину). Затем вы можете поместить это в матричную форму или оставить как есть, чтобы построить тепловую карту в ggplot и т. д.
полный Пример
setkey(dt, id)
c <- dt[dt, allow.cartesian=T][, list(Cor = cor(value, value.1)), by = list(group, group.1)]
c
group group.1 Cor
1: a a 1.0000000
2: b a 0.1556371
3: a b 0.1556371
4: b b 1.0000000
dcast(c, group~group.1, value.var = "Cor")
group a b
1 a 1.0000000 0.1556371
2 b 0.1556371 1.0000000