以下是我的数据框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 -1
与C
中的下一个值之间的差异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个值是相同的,那么程序不应该考虑减去值A
和C
例如,{ {1}}它的值更改为1,但程序不应该考虑该数据指向B11 ==1
之间的差异,因为A11 and C12
的值在C
时仍然在4的计数内} 已经改变。同样适用于B
的数据点。
答案 0 :(得分:3)
我们可以尝试使用data.table
。将'data.frame'转换为'data.table'(setDT(df1)
),shift
'C'列以获取下一个值('C1'),按运行长度id分组'B'并指定i
(abs(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]