我需要实现一个根据某些条件将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 loop
,loop
也无法执行。我想避免35
,因为如果我们处理大量数据,它的执行时间会更长。
数据框来自发布的问题here
下面的是我尝试使用上面引用的帖子的脚本。
for loop
答案 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
您会发现您的初始循环每行迭代一次,而此解决方案每非零值只迭代一次。