найти последовательные дни с условием - PullRequest
0 голосов
/ 20 февраля 2019

Я хочу добавить новый столбец в моем фрейме данных, который подсчитывает количество последовательных дней с условием: подсчитать количество последовательных дней, если «возврат» превышает 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 голосов
/ 20 февраля 2019

Опция, использующая базы R ave и data.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)
0 голосов
/ 20 февраля 2019

Одна 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, он создает последовательность вокруг идентификатора группы длин серий, в противном случае присваивает.Наконец, он разгруппирует и удаляет избыточную переменную.

Или то же самое, но генерирует последовательность с помощью 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)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...