如果这些值按组存储在data.table的单个列中(除了将data.table转换为矩阵之外),是否有一种优雅计算值之间相关性的方法?
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
任何评论或帮助都非常感谢。
答案 0 :(得分:6)
data.table
没有简单的方法可以做到这一点。您提供的第一种方式:
cor(dt["a"]$value, dt["b"]$value)
可能是最简单的。
另一种方法是reshape
data.table
从"long"
格式到"wide"
格式:
> 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
版本&gt; = 1.9.0,那么您可以使用dcast.data.table
而不是更快。查看this post了解详情。
dcast.data.table(dt, id ~ group)
答案 1 :(得分:5)
我不知道如何立即以矩阵形式获取它,但我觉得这个解决方案很有用:
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
答案 2 :(得分:4)
我已经找到了一个简单的替代方法来做到这一点。你实际上与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