【问题标题】:How to find linear regression between groups using data.table?如何使用 data.table 找到组之间的线性回归?
【发布时间】:2021-06-24 18:34:11
【问题描述】:

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

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. 解决方案需要找到所有组的组合。

【问题讨论】:

  • 我猜你只是在寻找 a, b 而不是 b, a 对吧?
  • 我正在寻找 (a,b) 和 (b,a),因为每个回归都会产生不同的结果。
  • 还有一点,这些组的大小可能不同。 data.table 将类似于 - dt &lt;- data.table(group = c(rep(1:4, 100), rep(5, 30)), a = rnorm(430))
  • 感谢@Arun 处理li &lt; 0 的情况,请发布此答案。
  • 当然,我会尝试foreach。感谢您的提示!

标签: r data.table regression


【解决方案1】:

使用新数据,我们可以将split 的数据按“分组”组合成list。然后,在listnames上使用combn进行成对组合,提取list元素(s1s2),检查是否有any公共'时间'(@987654330 @)。使用基于length 的条件,即如果有公共元素,则在相应的“值”列上应用lm,创建一个带有汇总coef 以及组名和rbind 的data.table 987654335@元素

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

【讨论】:

  • 谢谢@Arun!它确实可以处理a~b 等情况,但不会产生b~a 的其他情况。您是否可以更新代码以处理b~a 场景?
  • @Saurabh 为此,我们需要expand.gridCJ,然后删除相同的那些
  • 好的,我会尽量做到的。谢谢!
  • @Saurabh 我之前没有使用它,因为你提到数据真的很大,有很多组
  • 感谢@Arun 的精彩回答。
猜你喜欢
  • 2021-09-08
  • 2023-04-03
  • 1970-01-01
  • 2014-07-19
  • 1970-01-01
  • 1970-01-01
  • 2015-12-11
  • 2017-10-23
  • 2021-12-08
相关资源
最近更新 更多