R:将开始/结束日期转换为数据系列

时间:2016-03-06 16:19:52

标签: r

我有以下代表用户订阅的数据框:

User  StartDate   EndDate
1     2015-09-03  2015-10-17
2     2015-10-27  2015-12-25
...

如何将其转换为一个时间序列,该时间序列为我提供了一段时间内活跃的每月订阅数量(假设该月份至少在该月的一天内有效)。这样的事情(基于上面的例子,假设只有2条记录):

Month    Count
2015-08  0
2015-09  1
2015-10  2
2015-11  1
2015-12  1
2016-01  0

Rem:我为时间序列选择了一些任意的开始和结束日期,以使示例清晰。

2 个答案:

答案 0 :(得分:0)

准备数据并确保日期列实际存储为日期:

data <- read.table(text = "User  StartDate   EndDate
1     2015-09-03  2015-10-17
2     2015-10-27  2015-12-25", header = TRUE)
data$StartDate <- as.Date(StartDate)
data$EndDate <- as.Date(EndDate))

此函数返回一个包含订阅内所有月份的向量:

library(lubridate)
subscr_month <- function(start, end) {

  start <- floor_date(start, "month")
  seq <- seq(start, end, by = "1 month")
  months <- format(seq, format = "%Y-%m")
  return(months)

}

它使用floor_date()包中的函数lubridate。有必要对开始日期进行舍入,否则上个月可能会丢失。例如,对于用户2,如果您将两个月添加到开始日期,则最终会在结束日期之后的2015-12-27结束,以便seq中不包含12月的日期。最后一行将日期转换为仅包含年份和月份的字符。

现在,您可以使用mapply()将此功能应用于数据的每个开始和结束日期。之后,table()会在结果列表中创建一个包含所有日期计数的表格:

all_month <- mapply(subscr_month, data$StartDate, data$EndDate, SIMPLIFY = FALSE)
table(unlist(all_month))
## 2015-09 2015-10 2015-11 2015-12 
##       1       2       1       1 

您还可以将表格转换为数据框:

as.data.frame(table(unlist(all_month)))
##      Var1 Freq
## 1 2015-09    1
## 2 2015-10    2
## 3 2015-11    1
## 4 2015-12    1

您的示例输出还包括未出现在数据集中的月份计数。如果你想拥有它,你可以将月份矢量转换为一个因子,并将水平设置为你想要包括的所有月份:

month_list <- format(seq(as.Date("2015-08-01"), as.Date("2016-01-01"), by = "1 month"), format = "%Y-%m")
all_month_factor <- factor(unlist(all_month), levels = month_list)
table(all_month_factor)
## all_month_factor
## 2015-08 2015-09 2015-10 2015-11 2015-12 2016-01 
##       0       1       2       1       1       0 

答案 1 :(得分:0)

阅读上述数据框。

df = structure(list(StartDate = structure(c(16681, 16735), class = "Date"), 
    EndDate = structure(c(16735, 16794), class = "Date")), class = "data.frame", .Names = c("StartDate", 
"EndDate"), row.names = c(NA, -2L))

可以充分利用do包中的dplyrseq

df %>%
      rowwise() %>% do({
        w <- seq(.$StartDate,.$EndDate,by = "15 days") #for month difference less than 1 complete month
        m <- format(w,"%Y-%m") %>% unique 
        data.frame(Month = m)
      }) %>%
      group_by(Month) %>%
      summarise(Count = length(Month))