问题描述
我有一些时间序列,每个日期的对应数字为0或1。例如:
date value
1 0
2 0
3 1
4 1
5 1
6 0
7 1
8 1
因此,我想对连续的1´s进行计数,例如对于3-5号,总和应为3,然后从7号开始重新计数。如果此总和低于6,则应将1´转换为0´。
解决方法
我首先创建一个分组变量,然后使用它来聚合数据集。
d = data.frame("date"=1:12,"value"=c(1,1,0))
d$group = 1
for(i in 2:dim(d)[1]){
if(d$value[i]==d$value[i-1]){
d$group[i]=d$group[i-1]
} else {
d$group[i]=d$group[i-1]+1
}
}
nd = data.frame("Group"=unique(d$group),"Start"=aggregate(d$date~d$group,FUN=min)[,2],"End"=aggregate(d$date~d$group,FUN=max)[,"Count"=aggregate(d$value~d$group,FUN=sum)[,2])
此数据的输出为:
> d ## Input data
date value
1 1 1
2 2 1
3 3 0
4 4 0
5 5 1
6 6 1
7 7 1
8 8 1
9 9 0
10 10 0
11 11 1
12 12 0
> nd ## All groups
Group Start End Count
1 1 1 2 2
2 2 3 4 0
3 3 5 8 4
4 4 9 10 0
5 5 11 11 1
6 6 12 12 0
> nd[nd$Count>0,] ## Just the groups with 1 in them:
Group Start End Count
1 1 1 2 2
3 3 5 8 4
5 5 11 11 1
,
library(dplyr)
data.frame(
date = 1:8,value = c(0,1)
) %>%
mutate(
count = rle(value) %>%
{list(.$lengths * .$values,.$lengths)} %>%
{rep(x = .[[1]],times = .[[2]])},count_1 = ifelse(count < 6,count)
)
给予:
date value count count_1
1 1 0 0 0
2 2 0 0 0
3 3 1 3 0
4 4 1 3 0
5 5 1 3 0
6 6 0 0 0
7 7 1 2 0
8 8 1 2 0
,
另一种看起来像您期望的解决方案:
d = data.frame("date"=1:20,0))
repl <- rle(d$value)
rep_lengths <- rep(repl$lengths,repl$lengths)
rep_lengths[rep_lengths < 6] <- 0
d$value <- rep_lengths
返回
> d
date value
1 1 0
2 2 0
3 3 0
4 4 0
5 5 0
6 6 0
7 7 0
8 8 0
9 9 0
10 10 0
11 11 0
12 12 0
13 13 7
14 14 7
15 15 7
16 16 7
17 17 7
18 18 7
19 19 7
20 20 0
,
您可以使用rle
来计数连续数,并使用ifelse
将低6设置为0
:
y <- rle(x$value)
y[[2]] <- y[[1]] * y[[2]]
y[[2]] <- ifelse(y[[2]] < 6,y[[2]])
inverse.rle(y)
#[1] 0 0 0 0 0 0 0 0
数据:
x <- data.frame(date = 1:8,1))