寻找连续的有条件的日子

时间:2019-02-20 09:09:34

标签: r

我想在我的数据框中添加一个新列,该列用于对具有以下条件的连续天数进行计数:如果“返回”值大于3,则对连续天数进行计数。

这是我的数据集:

df <- tibble( 
date = lubridate::today() +0:9,
return= c(1,2.5,2,3,5,6.5,1,9,3,2))

我的数据框应如下所示:

   date       return    Consec_days
   <date>      <dbl>      <dbl>
 1 2019-02-20    1         NA
 2 2019-02-21    2.5       NA
 3 2019-02-22    2         NA
 4 2019-02-23    3         NA
 5 2019-02-24    5         1
 6 2019-02-25    6.5       2
 7 2019-02-26    1         NA
 8 2019-02-27    9         NA
 9 2019-02-28    3         1
10 2019-03-01    2         NA

如果不满足条件,请给我“ NA”或“ 0”

我已经尝试过:

df$Consec_Days <- with(df, ave(return, data.table::rleid(return > 3), 
                               FUN = function(x) ifelse(return > 3, seq_along(x), 0L)))

但是它不起作用。有人可以帮我吗?

2 个答案:

答案 0 :(得分:2)

使用底数R avedata.table::rleid的选项

library(data.table)
df$Consec_days <- with(df, (return > 3) * ave(return, rleid(return > 3), FUN = seq_along))


#     date       return Consec_days
#   <date>      <dbl>       <dbl>
# 1 2019-02-20    1             0
# 2 2019-02-21    2.5           0
# 3 2019-02-22    2             0
# 4 2019-02-23    3             0
# 5 2019-02-24    5             1
# 6 2019-02-25    6.5           2
# 7 2019-02-26    1             0
# 8 2019-02-27    9             1
# 9 2019-02-28    3             0
#10 2019-03-01    2             0

使用rleid(return > 3)创建分组,然后使用seq_along并为每个分组创建观察顺序

with(df, ave(return, rleid(return > 3), FUN = seq_along))
# [1] 1 2 3 4 1 2 1 1 1 2

我们将其乘以(return > 3),以保留大于3的观测值,其余的全部变为0。


将其翻译成dplyr我们可以做到

library(dplyr)

df %>%
  group_by(group = rleid(return > 3)) %>%
  mutate(consec_days = (return > 3) * row_number()) %>%
  ungroup() %>%
  select(-group)

答案 1 :(得分:1)

一种dplyr可能是:

df %>%
 group_by(return_rleid = {return_rleid = rle(return > 3); rep(seq_along(return_rleid$lengths), return_rleid$lengths)}) %>%
 mutate(Consec_days = ifelse(return <= 3, NA, seq_along(return_rleid))) %>%
 ungroup() %>% 
 select(-return_rleid)

   date       return Consec_days
   <date>      <dbl>       <int>
 1 2019-02-20   1.00          NA
 2 2019-02-21   2.50          NA
 3 2019-02-22   2.00          NA
 4 2019-02-23   3.00          NA
 5 2019-02-24   5.00           1
 6 2019-02-25   6.50           2
 7 2019-02-26   1.00          NA
 8 2019-02-27   9.00           1
 9 2019-02-28   3.00          NA
10 2019-03-01   2.00          NA

首先,它按照游程长度组ID进行分组。其次,如果“ return”大于3,它将在游程长度组ID周围创建一个序列,否则进行分配。最后,它取消分组并删除冗余变量。

相同,但由gl()生成序列:

df %>%
 group_by(return_rleid = {return_rleid = rle(return > 3); rep(seq_along(return_rleid$lengths), return_rleid$lengths)}) %>%
 mutate(Consec_days = ifelse(return <= 3, NA, gl(length(return_rleid), 1))) %>%
 ungroup() %>% 
 select(-return_rleid)