【问题标题】:R: converting start/end dates into data seriesR:将开始/结束日期转换为数据系列
【发布时间】:2016-03-06 16:19:52
【问题描述】:

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

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:我为时间序列取了一些任意的开始和结束日期,以使示例清晰。

【问题讨论】:

    标签: r


    【解决方案1】:

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

    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)
    
    }
    

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

    现在,您可以使用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 
    

    【讨论】:

      【解决方案2】:

      读取提到的数据框。

      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))
      

      可以在dplyr包和seq中充分利用do

      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))
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-10-10
        • 2019-12-11
        • 2023-03-17
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多