事件计数器有条件

时间:2017-07-18 07:34:46

标签: r

下面的

是一个数据框df,其中包含1个变量ID,数据点数为500K,我需要执行event counter并符合以下条件。
1 即可。 event counter时增加ID == A 2 即可。尽管ID == A,但不应考虑前3个数据点用于计数器增量 下面显示了具有预期输出的数据框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行不满足条件,因此Event Counter无增量。虽然第4,5行和第6行中ID ==A event counter不会增加(引用:条件2)。第12,13和14行的情况相同。

找到类似的问题,其中计数器在满足条件的每个数据点的遇到时递增,但是我的实现条件不同。

3 个答案:

答案 0 :(得分:5)

您可以将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))

在这种情况下,k = 4x == 4意味着在您想要增加之前需要3个ID == "A"个案例。您可以根据需要更改此号码。

结果等于您想要的输出:

all.equal(df$Event_counter, df$new)
#[1] TRUE

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我们重复每个值与每个序列相同的次数很长,即lengths

答案 1 :(得分:1)

这似乎可以做你想要的:

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)

输出

   ID Event_counter Event_counter_check
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

希望这有帮助!

答案 2 :(得分:0)

以下是使用splitlapply的基础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)
                       })))

使用与docendo-discimus的答案中类似的方法拆分ID变量,拆分相同ID的运行。此列表将输入lapply,检查该组是否由As组成,以及该组是否至少包含3个元素。如果是,则返回具有3 0s后跟1的向量,并返回0的剩余元素以匹配向量的长度。如果检查失败,则返回适当长度的0向量。

返回

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