如何使用 data.table 找到组之间的线性回归?

How to find linear regression between groups using data.table?

我试图找到以下数据集的所有可用组之间的线性回归。

library(data.table)
dt <- data.table(time = c(rep(rep(1:100, times = 1), 4), rep(1:30, times = 1)),
                   group = c(rep(c("a","b","c","d"), each = 100), rep("e", 30)), 
                   value = rnorm(430))
dt[]
      time group      value
  1:    1     a  0.1625954
  2:    2     a -1.2288462
  3:    3     a -0.1628570
  4:    4     a  1.0597886
  5:    5     a -1.1828334
 ---                      
426:   26     e -1.3762654
427:   27     e  0.3761436
428:   28     e -1.6982330
429:   29     e  0.1940263
430:   30     e -0.4631258

输出应该类似于

group1     group2      regression
a           b           1.2
a           c           0.3
b           c           0.5
d           a           4.3
...

我正在寻找仅使用 data.table 库的解决方案。

  1. 应该找到所有组的组合的线性回归。这包括案例 a~bb~a,因为每个案例的回归都会不同。
  2. 由于某些组的大小不同,因此应使用时间变量来查找任何一组组之间的公共行。
  3. 解决方案将需要找到组的所有组合。

有了新数据,我们可以split将数据'group'变成list。然后,在listnames上使用combn进行两两组合,提取出list个元素(s1s2),检查是否有 any 常见 'time' (intersect)。使用基于 length 的条件,即如果有共同元素,则在相应的 'value' 列上应用 lm,创建一个 data.table 并汇总 coef使用组名称和 rbind list 元素

library(data.table)
lst1 <- split(dt, dt$group)
rbindlist(combn(names(lst1), 2, FUN = function(x) {
      s1 <- lst1[[x[1]]]
      s2 <- lst1[[x[2]]]
      i1 <- intersect(s1$time, s2$time)
      if(length(i1) > 0) na.omit(s1[s2, on = .(time)][, 
        . (group1 = first(s1$group), group2 = first(s2$group), 
          regression = lm(i.value ~ value)$coef[2])]) 
       else
         data.table(group1 = first(s1$group), group2 = first(s2$group), 
         regression = NA_real_)}, simplify = FALSE))

-输出

     group1 group2  regression
 1:      a      b  0.03033996
 2:      a      c  0.06391242
 3:      a      d -0.09138112
 4:      a      e -0.27738183
 5:      b      c  0.05663270
 6:      b      d  0.05481604
 7:      b      e  0.27789495
 8:      c      d -0.13987978
 9:      c      e  0.16388299
10:      d      e  0.12380720

如果我们想要完整的组合,请使用 expand.gridCJ(来自 data.table

dt2 <- CJ(group1 = names(lst1), group2 = names(lst1))[group1 != group2]
dt2[, rbindlist(Map(function(x, y) {
       s1 <- lst1[[x]]
       s2 <- lst1[[y]]
       i1 <- intersect(s1$time, s2$time)
       if(length(i1) > 0) na.omit(s1[s2, on = .(time)][,
           data.table(group1 = x, group2 = y, 
          regresion = lm(i.value ~ value)$coef[2])]) else 
           data.table(group1 = x, group2 = y, regression = NA_real_)

        }, group1, group2))]

-输出

  group1 group2   regresion
 1:      a      b  0.03033996
 2:      a      c  0.06391242
 3:      a      d -0.09138112
 4:      a      e -0.27738183
 5:      b      a  0.03247826
 6:      b      c  0.05663270
 7:      b      d  0.05481604
 8:      b      e  0.27789495
 9:      c      a  0.07488082
10:      c      b  0.06198333
11:      c      d -0.13987978
12:      c      e  0.16388299
13:      d      a -0.09295215
14:      d      b  0.05208743
15:      d      c -0.12144302
16:      d      e  0.12380720
17:      e      a -0.25136439
18:      e      b  0.34052322
19:      e      c  0.28677255
20:      e      d  0.21435666