实现递减值的顺序计数器

时间:2017-08-17 05:06:05

标签: r dataframe

我需要实现一个根据某些条件将dec_cnt递减1的计数器。

以下是我的数据框df

 ID   A
  1   0
  2   0
  3   0
  4   1
  5   1
  6   0
  7   0
  8   0
  9   0
10    0
11    0
12    0
13    0
14    0
15    0
16   -1
17    1
18    0
19    1
20    0
21   -1
22    0
23    0
24   -1
25    0
26    0
27    0
28    0
29    0
30    0
31    0
32    0
33    0
34    0

条件是
一个。计数器应从A==1 or -1的数据点开始,并开始递减计数器的下一个16值,例如A == 1的值ID 4,所以从{{1}开始直到ID == 4递减计数器应该从值ID==19开始实现,直到计数器为15。另请注意,如果此范围之间存在任何0,则应忽略它。 湾我还需要实施A== 1/-1列,在retain_A中保留A的值。

以下是我的预期输出。

counter

几天前发布了类似的问题,解决方案使用了 ID A retain_A dec_cnt 1 0 NA NA 2 0 NA NA 3 0 NA NA 4 1 1 15 5 1 1 14 6 0 1 13 7 0 1 12 8 0 1 11 9 0 1 10 10 0 1 9 11 0 1 8 12 0 1 7 13 0 1 6 14 0 1 5 15 0 1 4 16 -1 1 3 17 1 1 2 18 0 1 1 19 1 1 0 20 0 NA NA 21 -1 -1 15 22 0 -1 14 23 0 -1 13 24 -1 -1 12 25 0 -1 11 26 0 -1 10 27 0 -1 9 28 0 -1 8 29 0 -1 7 30 0 -1 6 31 0 -1 5 32 0 -1 4 33 0 -1 3 34 0 -1 2 ,如果数据点数超过for looploop也无法执行。我想避免35,因为如果我们处理大量数据,它的执行时间会更长。

数据框来自发布的问题here

下面的

是我尝试使用上面引用的帖子的脚本。

for loop

1 个答案:

答案 0 :(得分:2)

我认为避免任何类型的循环for或其他方式都是现实的。也许更现实的目标是避免迭代每个值的循环,无论它是否相关。

从2列输入开始,让我们预先设置空列:

dat$retain_A <- NA
dat$dec_cnt  <- NA

在这里,我们可以获得一些效率:我们可以知道,如果它现在匹配-1/1,那么

ind <- which(dat$A %in% c(-1,1))
last_match <- 0
ind
# [1]  4  5 16 17 19 21 24

诀窍是跟踪last_match并丢弃它与接下来的15个条目之间的任何索引。

ind <- ind[ind > last_match]
while (length(ind) > 0) {
  i <- seq(ind[1], min(ind[1] + 15, nrow(dat)))
  dat$dec_cnt[i] <- head(15:0, n = length(i))
  dat$retain_A[i] <- dat$A[ ind[1] ]
  last_match <- ind[1] + 15
  ind <- ind[ind > last_match]
}
dat
#    ID  A retain_A dec_cnt
# 1   1  0       NA      NA
# 2   2  0       NA      NA
# 3   3  0       NA      NA
# 4   4  1        1      15
# 5   5  1        1      14
# 6   6  0        1      13
# 7   7  0        1      12
# 8   8  0        1      11
# 9   9  0        1      10
# 10 10  0        1       9
# 11 11  0        1       8
# 12 12  0        1       7
# 13 13  0        1       6
# 14 14  0        1       5
# 15 15  0        1       4
# 16 16 -1        1       3
# 17 17  1        1       2
# 18 18  0        1       1
# 19 19  1        1       0
# 20 20  0       NA      NA
# 21 21 -1       -1      15
# 22 22  0       -1      14
# 23 23  0       -1      13
# 24 24 -1       -1      12
# 25 25  0       -1      11
# 26 26  0       -1      10
# 27 27  0       -1       9
# 28 28  0       -1       8
# 29 29  0       -1       7
# 30 30  0       -1       6
# 31 31  0       -1       5
# 32 32  0       -1       4
# 33 33  0       -1       3
# 34 34  0       -1       2

您会发现您的初始循环每行迭代一次,而此解决方案每非零值只迭代一次。