根据另一列

时间:2017-07-24 10:45:15

标签: r dataframe

以下是我的数据框df,它有3个变量和大约100k个数据点,

   ID   A   B   C
   1    35  0   0
   2    28  0   0
   3    36  0   0
   4    99  0   0 
   5    25  1   0
   6    65  1   0
   7    98  1   0
   8    95  1   0
   9    67  0   65
  10    95  0   65 
  11    94  0   65
  12    4   0   65
  13    2   -1  0
  14    62  -1  0
  15    95  -1  0
  16    25  -1  0
  17    36  0   19.5
  18    3   0   19.5

现在,我想创建另一个变量D,其中包含A的最后一个数据点B == 1 or -1C中的下一个值之间的差异B == 1 or -1

预期输出

    ID  A   B   C      D
     1  35  0   0      0
     2  28  0   0      0
     3  36  0   0      0
     4  99  0   0      0
     5  25  1   0      0
     6  65  1   0      0
     7  98  1   0      0
     8  95  1   0     30
     9  67  0   65     0
    10  95  0   65     0
    11  94  0   65     0
    12  4   0   65     0
    13  2   -1  0      0
    14  62  -1  0      0
    15  95  -1  0      0
    16  25  -1  0    5.5
    17  36  0   19.5    0
    18  3   0   19.5    0

注意
 例如。 D8 = A8-c9,类似D16 = A16 - C17,这一直持续到数据框结束。

预期输出更新

    ID  A   B   C       D
     1  35  0   0       0
     2  28  0   0       0
     3  36  0   0       0
     4  99  0   0       0
     5  25  1   0       0
     6  65  1   0       0
     7  98  1   0       0
     8  95  1   0       30
     9  67  0   65      0
    10  95  0   65      0
    11  94  1   65      0
    12  4   0   65      0
    13  2   -1  0       0
    14  62  -1  0       0
    15  95  -1  0       0
    16  25  -1  0      5.5
    17  36  0   19.5    0
    18  3   0   19.5    0  
    19  5   0   19.5    0  
    20  68  1   19.5    0 
    21  17  0   0       0 

更新了问题

另一个条件是,如果列C中的值对于接下来的4个值是相同的,那么程序不应该考虑减去值AC例如,{ {1}}它的值更改为1,但程序不应该考虑该数据指向B11 ==1之间的差异,因为A11 and C12的值在C时仍然在4的计数内} 已经改变。同样适用于B的数据点。

2 个答案:

答案 0 :(得分:3)

我们可以尝试使用data.table。将'data.frame'转换为'data.table'(setDT(df1)),shift'C'列以获取下一个值('C1'),按运行长度id分组'B'并指定iabs(B)==1),我们将'D'指定为'A'和'C1'(A[.N] - C1[.N])的最后值之间的差异,指定列不需要NULL,并将'D'中的值更改为0,除了由分组变量(rleid(B))确定的最后一个元素

library(data.table)
setDT(df1)[, C1 := shift(C, type = 'lead')][abs(B)==1, 
             D := A[.N] - C1[.N], .(grp = rleid(B))][, C1 := NULL]
df1[df1[,.I[seq_len(.N) != .N] , rleid(B)]$V1, D := NA][is.na(D), D := 0][]
#    ID  A  B    C    D
# 1:  1 35  0  0.0  0.0
# 2:  2 28  0  0.0  0.0
# 3:  3 36  0  0.0  0.0
# 4:  4 99  0  0.0  0.0
# 5:  5 25  1  0.0  0.0
# 6:  6 65  1  0.0  0.0
# 7:  7 98  1  0.0  0.0
# 8:  8 95  1  0.0 30.0
# 9:  9 67  0 65.0  0.0
#10: 10 95  0 65.0  0.0
#11: 11 94  0 65.0  0.0
#12: 12  4  0 65.0  0.0
#13: 13  2 -1  0.0  0.0
#14: 14 62 -1  0.0  0.0
#15: 15 95 -1  0.0  0.0
#16: 16 25 -1  0.0  5.5
#17: 17 36  0 19.5  0.0
#18: 18  3  0 19.5  0.0

答案 1 :(得分:1)

或者使用基地R你可以尝试:

  dat$new <- 0

  ind <- cumsum(rle(dat$B)$lengths)[rle(dat$B)$values%in%c(1,-1)]

  dat[ind,"new"] <- dat[ind,"A"] - lead(dat[,"C"])[ind]