Разница в датах на основе значения отдельной переменной - PullRequest
1 голос
/ 29 мая 2020

У меня есть фрейм данных, который выглядит следующим образом:

        Date Value Value_Increase
1 2020-05-01     5          FALSE
2 2020-05-02     4          FALSE
3 2020-05-03    10           TRUE
4 2020-05-04     9          FALSE
5 2020-05-05     7          FALSE
6 2020-05-06    12           TRUE
7 2020-05-07     8          FALSE

Я хочу создать новый столбец, в котором будет указано количество дней с момента увеличения столбца «Значение».

Результаты будет выглядеть как фрейм данных ниже.

        Date Value Value_Increase Days_Since_Value_Increase
1 2020-05-01     5          FALSE                        NA
2 2020-05-02     4          FALSE                        NA
3 2020-05-03    10           TRUE                        NA
4 2020-05-04     9          FALSE                         1
5 2020-05-05     7          FALSE                         2
6 2020-05-06    12           TRUE                         3
7 2020-05-07     8          FALSE                         1

Спасибо за любую помощь или предложение, особенно за те, которые могут использовать подход dplyr.

Код для создания рабочего примера:

Date <- as.Date(c("2020-05-01", "2020-05-02", "2020-05-03", "2020-05-04", "2020-05-05", "2020-05-06", "2020-05-07"))
Value <- c(5, 4, 10, 9, 7, 12, 8)
Value_Increase <- c(FALSE, FALSE, TRUE, FALSE, FALSE, TRUE, FALSE)
df <- data.frame(Date, Value, Value_Increase, Days_Since_Value_Increase)

Ответы [ 3 ]

1 голос
/ 29 мая 2020

Мы можем использовать case_when из dplyr после создания группирующей переменной с cumsum и lag из 'Value_Increase'

library(dplyr)
df %>%
  group_by(g = cumsum(lag(Value_Increase, default = 0))) %>%
  mutate(Days_Since_Value_Increase = case_when(g != 0 ~  row_number())) %>%
  ungroup %>%
  select(-g)
# A tibble: 7 x 5
#  Date       Value Value_Increase Drop_From_Prev_Value Days_Since_Value_Increase
#  <date>     <dbl> <lgl>                         <dbl>                     <int>
#1 2020-05-01     5 FALSE                            NA                        NA
#2 2020-05-02     4 FALSE                             1                        NA
#3 2020-05-03    10 TRUE                             -6                        NA
#4 2020-05-04     9 FALSE                             1                         1
#5 2020-05-05     7 FALSE                             2                         2
#6 2020-05-06    12 TRUE                             -5                         3
#7 2020-05-07     8 FALSE                             4                         1

Или с rowid из data.table

library(data.table)
df %>% 
  mutate(Days_Since_Value_Increase = replace(rowid(cumsum(lag(Value_Increase,
            default = 0))), 
             seq_len(which.max(Value_Increase)), NA))
1 голос
/ 29 мая 2020

Если вы хотите сделать его устойчивым к отсутствующим дням

df %>%
  group_by(g = cumsum(lag(Value_Increase, default = 0))) %>%
  mutate(Days_Since_Value_Increase = ifelse(g == 0, NA, Date - min(Date) + 1))`

# A tibble: 7 x 4
# Groups:   g [3]
  Date       Value     g Days_Since_Value_Increase
  <date>     <dbl> <dbl>                     <dbl>
1 2020-05-01     5     0                        NA
2 2020-05-02     4     0                        NA
3 2020-05-03    10     0                        NA
4 2020-05-04     9     1                         1
5 2020-05-05     7     1                         2
6 2020-05-06    12     1                         3
7 2020-05-07     8     2                         1
1 голос
/ 29 мая 2020

Один из подходов с tidyverse - сгруппировать ваши результаты с cumsum, чтобы дни, прошедшие с момента последнего увеличения значения, были представлены row_number() внутри группы. Это предполагает разницу между строками в один день.

library(tidyverse)

df %>%
  group_by(g = cumsum(lag(Value_Increase, default = 0))) %>%
  mutate(Days_Since_Value_Increase = ifelse(g == 0, NA, row_number()))

Вывод

# A tibble: 7 x 5
# Groups:   g [3]
  Date       Value Value_Increase     g Days_Since_Value_Increase
  <date>     <dbl> <lgl>          <dbl>                     <int>
1 2020-05-01     5 FALSE              0                        NA
2 2020-05-02     4 FALSE              0                        NA
3 2020-05-03    10 TRUE               0                        NA
4 2020-05-04     9 FALSE              1                         1
5 2020-05-05     7 FALSE              1                         2
6 2020-05-06    12 TRUE               1                         3
7 2020-05-07     8 FALSE              2                         1
...