首页 文章

与组或外部变量中的早期实例的差异

提问于
浏览
4

我有数据

dat1 <- data.table(id=1:9,
                   group=c(1,1,2,2,2,3,3,3,3),
                   t=c(14,17,20,21,26,89,90,95,99),
                   index=c(1,2,1,2,3,1,2,3,4)
                  )

我想根据 index 计算 t 与前一个值的差异 . 对于每个组的第一个实例,我想计算一些外部变量的差异

dat2 <- data.table(group=c(1,2,3),
                   start=c(10,15,80)
                  )

这样可以获得以下结果:

> res 
   id group  t index dif
1:  1     1 14     1   4
2:  2     1 17     2   3
3:  3     2 20     1   5
4:  4     2 21     2   1
5:  5     2 26     3   5
6:  6     3 89     1   9
7:  7     3 90     2   1
8:  8     3 95     3   5
9:  9     3 99     4   4

我试过用

dat1[ , ifelse(index == min(index), dif := t - dat2$start, dif := t - t[-1]), by = group]

但我不确定在一步中引用同一组的其他元素和外部元素 . 这是否可以使用data.table?

3 回答

  • 3

    可能的解决方案:

    dat1[, dif := ifelse(index == min(index),
                         t - dat2$start[match(.BY, dat2$group)],
                         t - shift(t))
         , by = group][]
    

    这使:

    id group t index dif
    1:1 1 14 1 4
    2:2 1 17 2 3
    3:3 2 20 1 5
    4:4 2 21 2 1
    5:5 2 26 3 5
    6:6 3 89 1 9
    7:7 3 90 2 1
    8:8 3 95 3 5
    9:9 3 99 4 4

    或@jogo在评论中提出的避免ifelse的变体:

    dat1[, dif := t - shift(t), by = group
         ][index == 1, dif := t - dat2[group==.BY, start], by = group][]
    
  • 4

    我会尽量避免 ifelse 并使用data.tables高效的join-capabilities:

    dat1[dat2, on = "group",                                # join on group
              start := i.start][,                           # add start value
              diff  := diff(c(start[1L], t)), by = group][, # compute difference
              start := NULL]                                # remove start value
    

    结果表是:

    #   id group  t index diff
    #1:  1     1 14     1    4
    #2:  2     1 17     2    3
    #3:  3     2 20     1    5
    #4:  4     2 21     2    1
    #5:  5     2 26     3    5
    #6:  6     3 89     1    9
    #7:  7     3 90     2    1
    #8:  8     3 95     3    5
    #9:  9     3 99     4    4
    
  • 3

    您可以将 shift 与动态 fill 参数一起使用:使用 .BY 索引'dat2'以获取每个'group'的'start'值:

    dat1[ , dif := t - shift(t, fill = dat2[group == .BY, start]), by = group]
    
    #    id group  t index dif
    # 1:  1     1 14     1   4
    # 2:  2     1 17     2   3
    # 3:  3     2 20     1   5
    # 4:  4     2 21     2   1
    # 5:  5     2 26     3   5
    # 6:  6     3 89     1   9
    # 7:  7     3 90     2   1
    # 8:  8     3 95     3   5
    # 9:  9     3 99     4   4
    

    或者,您可以分步执行此操作 . 可能是品味问题,但我发现它比 ifelse 方式更透明 .

    首先是'normal' shift . 然后将'index'变量添加到'dat2'并执行更新连接 .

    dat1[ , dif := t - shift(t), by = group]
    
    dat2[ , index := 1]
    dat1[dat2, on = .(group, index), dif := t - start]
    

相关问题