【问题标题】:Correlation between groups in R data.tableR data.table中组之间的相关性
【发布时间】:2023-03-27 01:10:02
【问题描述】:

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

非常感谢任何 cmets 或帮助。

【问题讨论】:

    标签: r data.table correlation


    【解决方案1】:

    我后来找到了一个更简单的替代方法。实际上,您的 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
    

    【讨论】:

      【解决方案2】:

      我不知道有什么方法可以立即以矩阵形式获取它,但我发现这个解决方案很有用:

      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
      

      【讨论】:

        【解决方案3】:

        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 版本 >= 1.9.0,那么您可以改用 dcast.data.table,这会更快。更多信息请查看this post

        dcast.data.table(dt, id ~ group)
        

        【讨论】:

        • 你知道dcast.data.table吗?
        • 我想我以前遇到过它,但现在我深入挖掘,结果发现我被困在旧版本的 data.table
        • 1.8.11reshape 之前的版本不适用于data.tables,因为dcast.data.tablemelt.data.table 没有实现,所以你必须转换为@987654340 @ 并返回。
        • @ScottRitchie,不正确。我认为您对 Hadley 软件包中的基本功能感到困惑。 reshape 是一个基本函数,它适用于data.table所有 版本。 reshapereshape2 也是具有melt/cast 功能的包。 data.table &gt;= 1.9.0 版本实现 meltdcast 方法并导入 reshape2
        • @BramVisser,是的,没错。 dcast.data.table 充分利用了所有 data.table 内部结构,以及其他用 C 编写的基本要素。如果您遇到任何问题,请告诉我们 here。请记住,到目前为止,您必须完整地拼出 dcast.data.table 而不仅仅是 dcast .. 稍后会修复它。如果您只使用dcast,它将使用reshape2's dcast,这比dcast.data.table 慢得多。
        猜你喜欢
        • 1970-01-01
        • 2014-03-22
        • 2019-02-27
        • 1970-01-01
        • 1970-01-01
        • 2017-01-11
        • 2018-04-15
        • 1970-01-01
        • 2020-05-18
        相关资源
        最近更新 更多