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