R-如果发生事件,则最多连续几天进行计数

时间:2018-07-16 11:17:32

标签: r dataframe data.table

我有下一个数据表。

TIME       ZONE TEN
2018-07-12  N1  12
2018-07-13  N1  13
2018-07-14  N2  11
2018-07-15  N2  16
2018-07-16  N2  12

我想计算每个区域中TEN变量<15的连续天数,并添加一个连续天数最多的新列。输出应为:

TIME       ZONE TEN TEN_<_15
2018-07-12  N1  12  2
2018-07-13  N1  13  2
2018-07-14  N2  11  0
2018-07-15  N2  16  0
2018-07-16  N2  12  0

我已经尝试了下一个:

dataset[TEN < 15 ,TEN_<_15:= paste0(ZONE, "_", cumsum(!c(TRUE, diff(TIME) == 1))), by = ZONE]

但是它不会返回我想要的输出。

有什么想法吗?

谢谢

3 个答案:

答案 0 :(得分:3)

在基数R中:

dataset$`TEN_<_15` <-
  ave(dataset$TEN,dataset$ZONE,FUN = function(vec)
  with(rle(vec <15), max(lengths[values])))

dataset$`TEN_<_15`[dataset$`TEN_<_15` ==1] <- 0

#         TIME ZONE TEN TEN_<_15
# 1 2018-07-12   N1  12        2
# 2 2018-07-13   N1  13        2
# 3 2018-07-14   N2  11        0
# 4 2018-07-15   N2  16        0
# 5 2018-07-16   N2  12        0

翻译成tidyverse语法:

library(dplyr)
dataset %>%
  group_by(ZONE) %>%
  mutate(`TEN_<_15` = with(rle(TEN <15), max(lengths[values]))) %>%
  mutate_at("TEN_<_15",~ifelse(.x==1,0,.x))

# # A tibble: 5 x 4
# # Groups:   ZONE [2]
#          TIME   ZONE   TEN `TEN_<_15`
#       <fctr> <fctr> <int>      <dbl>
# 1 2018-07-12     N1    12          2
# 2 2018-07-13     N1    13          2
# 3 2018-07-14     N2    11          0
# 4 2018-07-15     N2    16          0
# 5 2018-07-16     N2    12          0

答案 1 :(得分:1)

使用基数R,您可以这样做:

dataset$`TEN_<_15` <- ave(dataset$TEN, dataset$ZONE, FUN = function(x){
  r <- rle(x < 15)
  r$values[r$values & r$lengths < 2] <- FALSE
  r$values*r$lengths
})

dataset
#       TIME ZONE TEN TEN_<_15
#1 2018-07-12   N1  12        2
#2 2018-07-13   N1  13        2
#3 2018-07-14   N2  11        0
#4 2018-07-15   N2  16        0
#5 2018-07-16   N2  12        0

数据。

dataset <- read.table(text = "
TIME       ZONE TEN
2018-07-12  N1  12
2018-07-13  N1  13
2018-07-14  N2  11
2018-07-15  N2  16
2018-07-16  N2  12                      
", header = TRUE)

答案 2 :(得分:0)

不确定我是否正确理解您的要求。无论如何,这是一种使用data.table的方法以及更多情况下的数据集:

#convert string to Date
DT[, TIME := as.Date(TIME, "%Y-%m-%d")][, 
    #group by ZONE and consecutive TEN less than 15, then 
    #if there are at least 1 row and gaps between dates are all ones, 
    #return number of rows
    LESS_THAN_15 := if (.N > 1L && all(diff(TIME) == 1L)) .N else 0L,
    by=.(ZONE, rleid(TEN < 15L))]
DT

输出:

          TIME ZONE TEN LESS_THAN_15
 1: 2018-07-12   N1  11            2
 2: 2018-07-13   N1  12            2
 3: 2018-07-14   N1  15            0
 4: 2018-07-20   N1  14            0
 5: 2018-08-11   N2   1            3
 6: 2018-08-12   N2   2            3
 7: 2018-08-13   N2   3            3
 8: 2018-08-17   N2  17            0
 9: 2018-08-19   N2   9            0
10: 2018-08-21   N2  11            0
11: 2018-08-23   N2  13            0
12: 2018-08-25   N2  15            0
13: 2018-09-01   N3   4            0
14: 2018-09-01   N3   5            0
15: 2018-09-03   N3   6            0

更多情况下的数据:

library(data.table)
DT <- fread("TIME       ZONE TEN
2018-07-12  N1  11
2018-07-13  N1  12
2018-07-14  N1  15
2018-07-20  N1  14
2018-08-11  N2  1
2018-08-12  N2  2
2018-08-13  N2  3
2018-08-17  N2  17
2018-08-19  N2  9
2018-08-21  N2  11
2018-08-23  N2  13
2018-08-25  N2  15
2018-09-01  N3  4
2018-09-01  N3  5
2018-09-03  N3  6")