изменение приращений даты в r

#r #sequence #dplyr

#r #последовательность #dplyr

Вопрос:

Я хочу создать инкрементную последовательность:

У меня есть фрейм данных dt <- data.table(Customer = c("a", "b", "c"), count = c(3, 4, 5), Date = c("2019-02-01","2019-05-01","2019-10-01"))

   Customer count       Date
1:        a     3 2019-02-01
2:        b     4 2019-05-01
3:        c     5 2019-10-01
  

Я реплицирую этот фрейм данных путем подсчета, используя: dt[rep(seq(1, nrow(dt)), dt$count)]

Результат, который я получаю, является

     Customer count       Date
 1:        a     3 2019-02-01
 2:        a     3 2019-02-01
 3:        a     3 2019-02-01
 4:        b     4 2019-05-01
 5:        b     4 2019-05-01
 6:        b     4 2019-05-01
 7:        b     4 2019-05-01
 8:        c     5 2019-10-01
 9:        c     5 2019-10-01
10:        c     5 2019-10-01
11:        c     5 2019-10-01
12:        c     5 2019-10-01
  

Есть ли способ добавить 3 месяца к инкрементным датам, чтобы я получил следующий результат?

     Customer count       Date
 1:        a     3 2019-02-01
 2:        a     3 2019-05-01
 3:        a     3 2019-08-01
 4:        b     4 2019-05-01
 5:        b     4 2019-08-01
 6:        b     4 2019-11-01
 7:        b     4 2020-02-01
 8:        c     5 2019-10-01
 9:        c     5 2020-01-01
10:        c     5 2020-04-01
11:        c     5 2020-07-01
12:        c     5 2020-10-01
  

Я был бы признателен за любую помощь.

Спасибо

Ответ №1:

Мы можем использовать months from lubridate и создать seq влияние, чтобы добавить 3 месяца в каждую строку, начиная с первого значения в каждом Customer .

 new_dt <- dt[rep(seq(1, nrow(dt)), dt$count)]

library(dplyr)
library(lubridate)

new_dt %>%
  group_by(Customer) %>%
  mutate(Date = as.Date(Date[1])   months(seq(0, length.out = n(), by = 3)))

#   Customer  count      Date      
#   <chr>    <dbl>     <date>    
# 1 a            3 2019-02-01
# 2 a            3 2019-05-01
# 3 a            3 2019-08-01
# 4 b            4 2019-05-01
# 5 b            4 2019-08-01
# 6 b            4 2019-11-01
# 7 b            4 2020-02-01
# 8 c            5 2019-10-01
# 9 c            5 2020-01-01
#10 c            5 2020-04-01
#11 c            5 2020-07-01
#12 c            5 2020-10-01
  

Та же логика может быть применена с помощью ave

 with(new_dt, ave(as.Date(Date), Customer, FUN = function(x) 
      x[1]   months(seq(0, length.out = length(x), by = 3))))

#[1] "2019-02-01" "2019-05-01" "2019-08-01" "2019-05-01" "2019-08-01" "2019-11-01"
#[7] "2020-02-01" "2019-10-01" "2020-01-01" "2020-04-01" "2020-07-01" "2020-10-01"
  

Ответ №2:

В базе R с lubridate

 library(lubridate)

new_dt$Date=as.Date(new_dt$Date) month(ave(new_dt$count,new_dt$Customer,FUN=function(x) cumsum(x)-x[1]))
new_dt
    Customer count       Date
 1:        a     3 2019-02-01
 2:        a     3 2019-02-04
 3:        a     3 2019-02-07
 4:        b     4 2019-05-01
 5:        b     4 2019-05-05
 6:        b     4 2019-05-09
 7:        b     4 2019-05-13
 8:        c     5 2019-10-01
 9:        c     5 2019-10-06
10:        c     5 2019-10-11
11:        c     5 2019-10-16
12:        c     5 2019-10-21
  

Ответ №3:

data.table Решение

 dt[, .(count, Date = as.Date(Date)   seq(0, count - 1) * months(3)), by = Customer]
#    Customer count       Date
# 1:        a     3 2019-02-01
# 2:        a     3 2019-05-01
# 3:        a     3 2019-08-01
# 4:        b     4 2019-05-01
# 5:        b     4 2019-08-01
# 6:        b     4 2019-11-01
# 7:        b     4 2020-02-01
# 8:        c     5 2019-10-01
# 9:        c     5 2020-01-01
#10:        c     5 2020-04-01
#11:        c     5 2020-07-01
#12:        c     5 2020-10-01