【问题标题】:Constructing Monthly Snapshots of Time Stamped Data in R在 R 中构建时间戳数据的月度快照
【发布时间】:2020-08-19 12:13:08
【问题描述】:

我面临的一个小问题。这里的理想化例子:

我有一个数据框,其中记录了对保险单的value 进行更改的日期。这看起来像这样:

df <- data.frame(policy_no  = c(1, 1, 1, 1, 2, 2, 2),
                 date_stamp = as.Date(c("2020-01-15", "2020-04-03", "2020-05-31", "2020-07-22", "2020-01-05", "2020-03-17", "2020-06-04" )),
                 value      = c(1000, 2000, 3000, 2000, 500, 1000, 500))

我有两个策略,policy_no 1 和 2。对于每个策略,我想编写一些代码来告诉我每个月 1 日 value 项目的状态。所以我的输出看起来像

df_output <- data.frame(policy_no =  c(rep(1, 8), rep(2, 8)),
                        as_at_date = c(seq(as.Date("2020-01-01"), by = "month", length.out = 8), seq(as.Date("2020-01-01"), by = "month", length.out = 8)),
                        value = c(NA, 1000, 1000, 1000, 2000, 3000, 3000, 2000, NA, 500, 500, 1000, 1000, 1000, 500, 500))

显然我可以编写一个循环来执行此操作(对于每个policy_no,对于每个as_at_date,给我value 以获得date_stamp &lt;= as_at_date 的最新快照),但这会很慢而且很笨重.我可以以某种方式将其矢量化吗?

特别欢迎基于tidyverse 的方法,但无论如何感谢任何建议。

非常感谢。

【问题讨论】:

    标签: r date dplyr


    【解决方案1】:

    这是一种方法。首先,为每个策略创建一个月度日期序列。然后,group_by 策略和月度日期,并仅过滤超出日期戳的那些月度日期。最后,使用slice 获取最后一行数据,其中包含最近的值。让我知道这是否是您的想法。

    library(tidyverse)
    library(lubridate)
    
    df %>%
      group_by(policy_no) %>%
      mutate(as_at_date = list(seq(floor_date(min(date_stamp), unit = "month"), ceiling_date(max(date_stamp), unit = "month"), by = "month"))) %>%
      unnest(cols = as_at_date) %>%
      group_by(policy_no, as_at_date) %>%
      filter(as_at_date > date_stamp) %>%
      slice(tail(row_number(), 1))
    

    如果您想包含一月份的 NA,您可以加入您的日期序列,这样所有月份都将包含在内:

    df_dates <- df %>%
      group_by(policy_no) %>%
      mutate(as_at_date = list(seq(floor_date(min(date_stamp), unit = "month"), ceiling_date(max(date_stamp), unit = "month"), by = "month"))) %>%
      unnest(cols = as_at_date) 
    
    df_dates %>%
      group_by(policy_no, as_at_date) %>%
      filter(as_at_date > date_stamp) %>%
      slice(tail(row_number(), 1)) %>%
      right_join(df_dates %>% select(policy_no, as_at_date) %>% distinct()) %>%
      arrange(policy_no, as_at_date) 
    

    输出

    # A tibble: 15 x 4
    # Groups:   policy_no, as_at_date [15]
       policy_no date_stamp value as_at_date
           <dbl> <date>     <dbl> <date>    
     1         1 NA            NA 2020-01-01
     2         1 2020-01-15  1000 2020-02-01
     3         1 2020-01-15  1000 2020-03-01
     4         1 2020-01-15  1000 2020-04-01
     5         1 2020-04-03  2000 2020-05-01
     6         1 2020-05-31  3000 2020-06-01
     7         1 2020-05-31  3000 2020-07-01
     8         1 2020-07-22  2000 2020-08-01
     9         2 NA            NA 2020-01-01
    10         2 2020-01-05   500 2020-02-01
    11         2 2020-01-05   500 2020-03-01
    12         2 2020-03-17  1000 2020-04-01
    13         2 2020-03-17  1000 2020-05-01
    14         2 2020-03-17  1000 2020-06-01
    15         2 2020-06-04   500 2020-07-01
    

    【讨论】:

      【解决方案2】:

      编辑:更新了按政策和月份排序的 df 请在下面找到解决方案:

      df <- data.frame(policy_no  = c(1, 1, 1, 1, 2, 2, 2,1,1,1, 2, 2, 2,1,1,1),
                       date_stamp = as.Date(c("2020-01-15", "2020-04-03", "2020-05-31", "2020-07-22", "2020-01-05", "2020-03-17", "2020-06-04", "2020-01-05", "2020-03-17", "2020-06-04","2020-03-01","2020-02-01","2020-01-01","2020-03-01","2020-02-01","2020-01-01" )),
                       value      = c(1000, 2000, 3000, 2000, 500, 1000, 500,500, 1000, 500, 500, 1000, 500,500, 1000, 500))
      df$date <- format(as.Date(df$date_stamp,format="%Y-%m-%d"), format = "%d")
      df$month <- format(as.Date(df$date_stamp,format="%Y-%m-%d"), format = "%m")
      
      df_temp <- df[df$date == "01",]
      df_temp <- df_temp[order(df_temp$policy_no,df_temp$month),1:3]
      

      【讨论】:

      • 谢谢,但这似乎并没有给我想要的。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-11-11
      • 1970-01-01
      • 1970-01-01
      • 2015-01-26
      • 2019-06-28
      • 2013-04-07
      相关资源
      最近更新 更多