Подсчет числа в группе, но перезапуск для непоследовательных дат - PullRequest
0 голосов
/ 14 января 2020

У меня есть данные, которые выглядят так:

sample <- data.frame(
  group = c("A","A","A","B","B","B"),
  date = c(as.Date("2014-12-31"),
           as.Date("2015-01-31"),
           as.Date("2015-02-28"),
           as.Date("2015-01-31"),
           as.Date("2015-03-31"),
           as.Date("2015-04-30")),
  obs = c(100, 200, 300, 50, 100, 150)
)

Обратите внимание, что переменная даты всегда принимает последнюю дату месяца. В табличном формате данные выглядят так:

  group       date obs
1     A 2014-12-31 100
2     A 2015-01-31 200
3     A 2015-02-28 300
4     B 2015-01-31  50
5     B 2015-03-31 100
6     B 2015-04-30 150

Я хочу создать четвертый столбец, который подсчитывает количество наблюдений в группе. ОДНАКО, я хочу, чтобы подсчет начался заново, если месяц не следует сразу за месяцем ранее. Вот как я хочу, чтобы это выглядело так:

  group       date obs num
1     A 2014-12-31 100   1
2     A 2015-01-31 200   2
3     A 2015-02-28 300   3
4     B 2015-01-31  50   1
5     B 2015-03-31 100   1
6     B 2015-04-30 150   2

Пока все, что я могу получить, это следующее:

library(tidyverse)
sample <- sample %>%
  arrange(date) %>%
  group_by(group) %>%
  mutate(num = row_number())

  group       date obs num
1     A 2014-12-31 100   1
2     A 2015-01-31 200   2
3     A 2015-02-28 300   3
4     B 2015-01-31  50   1
5     B 2015-03-31 100   2
6     B 2015-04-30 150   3

Любая помощь будет принята с благодарностью. Я также хочу иметь возможность делать то же самое, но с квартальными данными (вместо месячных).

Ответы [ 2 ]

1 голос
/ 15 января 2020

Мы можем использовать lubridate::days_in_month, чтобы получить количество дней в месяце, сравнить его с разницей текущего и прошлого date, чтобы создать новую группу. Затем мы можем назначить row_number() в каждой группе.

library(dplyr)

sample %>%
  group_by(group) %>%
  mutate(diff_days = cumsum(as.numeric(date - lag(date, default = first(date))) != 
                     lubridate::days_in_month(date))) %>%
  group_by(diff_days, add = TRUE) %>%
  mutate(num = row_number()) %>%
  ungroup() %>%
  select(-diff_days)


# group  date         obs   num
#  <fct> <date>     <dbl> <int>
#1 A     2014-12-31   100     1
#2 A     2015-01-31   200     2
#3 A     2015-02-28   300     3
#4 B     2015-01-31    50     1
#5 B     2015-03-31   100     1
#6 B     2015-04-30   150     2
0 голосов
/ 14 января 2020

Мы можем создать группу на основе diff ernece month от 'date' и если оно не равно 1, т.е. разница в один месяц

library(dplyr)
library(lubridate)
sample %>%
     arrange(group, date) %>% 
     group_by(group, mth = cumsum(c(TRUE, diff(month(date)) != 1))) %>% 
     mutate(num = row_number()) %>%
     ungroup %>%
     select(-mth)
# A tibble: 6 x 4
#  group date         obs   num
#  <fct> <date>     <dbl> <int>
#1 A     2015-01-31   100     1
#2 A     2015-02-28   200     2
#3 A     2015-03-31   300     3
#4 B     2015-01-31    50     1
#5 B     2015-03-31   100     1
#6 B     2015-04-30   150     2

Если год также необходимо учитывать

library(zoo)
sample %>%
    arrange(group, date) %>% 
    mutate(yearmon = as.yearmon(date)) %>% 
    group_by(group) %>%
    group_by(grp = cumsum(c(TRUE, as.integer(diff(yearmon) * 12)> 1)),
             add = TRUE ) %>% 
    mutate(num = row_number()) %>% 
    ungroup %>% 
    select(-grp, -yearmon)
# A tibble: 6 x 4
#  group date         obs   num
#  <fct> <date>     <dbl> <int>
#1 A     2015-01-31   100     1
#2 A     2015-02-28   200     2
#3 A     2015-03-31   300     3
#4 B     2015-01-31    50     1
#5 B     2015-03-31   100     1
#6 B     2015-04-30   150     2
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...