R 带条件的事件计数器

R 带条件的事件计数器,r,R,下面是一个数据帧df,它有一个变量ID和500K个数据点,我需要在以下条件下执行事件计数器。 1。当ID==A 2。计数器增量不应考虑前3个数据点,尽管ID==A 下面显示了具有预期输出的数据帧df ID Event Counter D 0 F 0 V 0 A 0 A 0 A 0 A 1 A 1 A

下面是一个数据帧
df
,它有一个变量
ID
和500K个数据点,我需要在以下条件下执行
事件计数器。
1。当
ID==A

2。计数器增量不应考虑前3个数据点,尽管
ID==A

下面显示了具有预期输出的数据帧
df

ID       Event Counter  
D          0  
F          0  
V          0
A          0  
A          0  
A          0
A          1  
A          1  
A          1
V          1  
F          1  
A          1
A          1
A          1  
A          2  
F          2  
G          2 
A          2  
A          2  
A          2  
A          3  
A          3  
请注意:-行号1、2和3不满足条件,因此
事件计数器中没有增量。尽管第4、5和6行中的
ID==A
,但
事件计数器将不会递增(参考:条件2)。第12、13和14行的情况相同


发现了类似的问题,即满足条件的每个数据点的计数器都会增加,但我的实现条件不同

这似乎是你想要的:

df = read.table(text="ID Event_counter 
D          0  
F          0  
V          0
A          0  
A          0  
A          0
A          1  
A          1  
A          1
V          1  
F          1  
A          1
A          1
A          1  
A          2  
F          2  
G          2 
A          2  
A          2  
A          2  
A          3  
A          3",header=TRUE)

indices = df$ID=="A"
reset.counter = indices!=c(NA,head(indices,-1))& indices==FALSE & c(NA,head(indices,-1))==TRUE
indices <- unname(split(indices, cumsum(seq_along(indices) %in% which(reset.counter))))
indices=unlist(lapply(indices, function(x) cumsum(x)==4 & x==TRUE))
df$Event_counter_check =  cumsum(indices)

希望这有帮助

您可以将
zoo::rollsum
rle
结合用于此类任务:

library(zoo)
x <- rollsumr(df$ID == "A", k=4, fill = NA)
df$new <- with(rle(!is.na(x) & x == 4), rep(cumsum(values), lengths))

rle
部件返回:

rle(!is.na(x) & x == 4)
#Run Length Encoding
#  lengths: int [1:6] 6 3 5 1 5 2
#  values : logi [1:6] FALSE TRUE FALSE TRUE FALSE TRUE

现在我们可以a)计算这些值的累积和,即0-1-1-2。。。b) 使用
rep
我们重复这些值的次数与每个序列的长度相同,即
长度

这里是一个使用
split
lappy
的基本R替代方案

dat$v3 <-
  cumsum(unlist(lapply(split(dat$ID,
                           with(rle(as.character(dat$ID)), rep(seq_along(values), lengths))),
                       function(x) {
                         v <- length(x)
                         if(x[1] == "A" && v > 3) rep(c(0, 1, 0), c(3, 1, v-4))
                         else rep(0, v)
                       })))

另一种情况:如果
A
连续有8个(或超过6个)值,该怎么办?它还会继续使用同一个计数器吗?@RonakShah如果值
A
超过6,如果连续出现,计数器将保持相同的值。只有当与事件
ID==a
发生偏差并返回到事件
ID==a
时,计数器才会增加。这太好了!我试图通过
rle
获得它,这是一个很好的解决方案。你能解释一下with语句的长度部分是如何工作的吗?将rep(cumsum(values)应用于rle(!is.na(x)&x==4)的值,留给您0 1 1 2 3。此函数如何根据长度值重复这些数字?@Florianmas,我添加了一些解释。啊,我明白了,我一开始忽略了rep语句……非常感谢!@FlorianMass您的代码也运行良好,非常感谢。谢谢,您太好了。我已经为下一次学习了Docendo的代码;)
rle(!is.na(x) & x == 4)
#Run Length Encoding
#  lengths: int [1:6] 6 3 5 1 5 2
#  values : logi [1:6] FALSE TRUE FALSE TRUE FALSE TRUE
dat$v3 <-
  cumsum(unlist(lapply(split(dat$ID,
                           with(rle(as.character(dat$ID)), rep(seq_along(values), lengths))),
                       function(x) {
                         v <- length(x)
                         if(x[1] == "A" && v > 3) rep(c(0, 1, 0), c(3, 1, v-4))
                         else rep(0, v)
                       })))
dat
   ID Event_Counter v3
1   D             0  0
2   F             0  0
3   V             0  0
4   A             0  0
5   A             0  0
6   A             0  0
7   A             1  1
8   A             1  1
9   A             1  1
10  V             1  1
11  F             1  1
12  A             1  1
13  A             1  1
14  A             1  1
15  A             2  2
16  F             2  2
17  G             2  2
18  A             2  2
19  A             2  2
20  A             2  2
21  A             3  3
22  A             3  3