首页 文章

R data.table中各组之间的相关性

提问于
浏览
9

如果这些值按组存储在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

任何评论或帮助非常感谢 .

3 回答

  • 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
    

    Update: 如果你正在使用 data.table 版本> = 1.9.0,那么你可以使用 dcast.data.table 而不是更快 . 有关详细信息,请查看this post .

    dcast.data.table(dt, id ~ group)
    
  • 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
    

    显然,如果你最终想要矩阵形式的那些,那么你可以使用 dcastdcast.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
    
  • 4

    我已经找到了一个简单的替代方法来做到这一点 . 你实际上非常接近你的 dt[, cor(value, value), by="group"] 方法 . 你真正需要的是先在日期上进行笛卡尔连接,然后分组 . 即

    dt[dt, allow.cartesian=T][, cor(value, value), by=list(group, group.1)]
    

    这样做的好处是它可以将系列连接在一起(而不是假设它们的长度相同) . 然后,您可以将其转换为矩阵形式,或将其保留为在ggplot等中绘制为热图的原样 .

    Full Example

    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
    

相关问题