计算连续数字

问题描述

我有一些时间序列,每个日期的对应数字为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))