【问题标题】:Multiple pairwise differences based on column name patterns基于列名模式的多个成对差异
【发布时间】:2020-09-14 12:59:45
【问题描述】:

我有一个data.table,dt:

dt

Id  v1 v2 v3 x1 x2 x3
1   7  1  3  5  6  8
2   1  3  5  6  8  5
3   3  5  6  8  5  1

v1、v2、v3 和 x1、x2、x3 是数值变量

我想从“v”列中减去“x”列,即计算差异v1 - x1v2 - x2 等。在我的真实数据中,我可能有 100 个这样的变量对。

期望的输出:

dt

Id  v1 v2 v3 x1 x2 x3 diff1 diff2 diff3
1   7  1  3  5  6  8   -2     -4    -3
2   1  3  5  6  8  5   -5     -5     0
3   3  5  6  8  5  1   -3      0     5


我尝试了以下方法:

newnames <- paste0("diff", 1:3)
v <- paste0("v", 1:3)
x <- paste0("x", 1:3)
dt[ , c(newnames) := get(v) - get(x)]

但是,这会导致 3 个相同的列都包含差异 v1 - x1

我知道可能的解决方案类似于

dt[ , .(v1 - x1, v2 - x2, v3 - x3)]

但是,如果我必须输入 100 个不像 v1 和 x1 那样简单的名称,那么这是一个相当长的代码,可能会出现很多打字错误。

我希望你能帮助我。

【问题讨论】:

  • 我对您的diff1/diff2/diff3 列有点困惑,它们看起来与v1-x1 等不对应?

标签: r data.table array-difference


【解决方案1】:

您可以根据列是否包含x进行拆分,然后取结果数据表的差异。

new_cols <- 
  do.call('-', split.default(dt[,-1], grepl('x', names(dt)[-1])))

dt[, paste0('diff', seq_along(new_cols)) := new_cols]

dt
#    Id v1 v2 v3 x1 x2 x3 diff1 diff2 diff3
# 1:  1  7  1  3  5  6  8     2    -5    -5
# 2:  2  1  3  5  6  8  5    -5    -5     0
# 3:  3  3  5  6  8  5  1    -5     0     5

或者使用与问题中的代码sn-p类似的逻辑你可以做

newnames <- paste0("diff",1:3)
v <- paste0("v",1:3)
x <- paste0("x",1:3)

dt[, (newnames) := Map('-', mget(v), mget(x))]

dt
#    Id v1 v2 v3 x1 x2 x3 diff1 diff2 diff3
# 1:  1  7  1  3  5  6  8     2    -5    -5
# 2:  2  1  3  5  6  8  5    -5    -5     0
# 3:  3  3  5  6  8  5  1    -5     0     5

【讨论】:

    【解决方案2】:

    您的数据看起来属于长格式,因此您进行的计算将变得微不足道:

    # reshape
    DT_long = melt(DT, id.vars='Id', measure.vars = patterns(v = '^v', x = '^x'))
    DT_long
    #       Id variable     v     x
    # 1:     1        1     7     5
    # 2:     2        1     1     6
    # 3:     3        1     3     8
    # 4:     1        2     1     6
    # 5:     2        2     3     8
    # 6:     3        2     5     5
    # 7:     1        3     3     8
    # 8:     2        3     5     5
    # 9:     3        3     6     1
    

    现在很简单:

    DT_long[ , diff := v - x][]
    #       Id variable     v     x  diff
    # 1:     1        1     7     5     2
    # 2:     2        1     1     6    -5
    # 3:     3        1     3     8    -5
    # 4:     1        2     1     6    -5
    # 5:     2        2     3     8    -5
    # 6:     3        2     5     5     0
    # 7:     1        3     3     8    -5
    # 8:     2        3     5     5     0
    # 9:     3        3     6     1     5
    

    然后您可以使用dcast 重新调整为宽格式,但通常值得考虑的是保持这种长格式的数据集是否更适合整个分析。

    【讨论】:

      【解决方案3】:

      您可以在循环中使用set

      library(data.table)
      
      DT <- fread('Id  v1 v2 v3 x1 x2 x3
      1   7  1  3  5  6  8
      2   1  3  5  6  8  5
      3   3  5  6  8  5  1')
      
      for (i in 1:3) {
        set(DT,j=paste0("Diff_",i),value = DT[[paste0("v",i)]]-DT[[paste0("x",i)]])
      }
      
      DT
      #>    Id v1 v2 v3 x1 x2 x3 Diff_1 Diff_2 Diff_3
      #> 1:  1  7  1  3  5  6  8      2     -5     -5
      #> 2:  2  1  3  5  6  8  5     -5     -5      0
      #> 3:  3  3  5  6  8  5  1     -5      0      5
      

      reprex package (v0.3.0) 于 2020 年 5 月 27 日创建

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2022-01-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-03-27
        • 1970-01-01
        相关资源
        最近更新 更多