R按id计算日期变量的连续数

时间:2018-10-11 04:00:55

标签: r count continuous

我有一个这样的数据库:

dat = data.frame(id = c(rep("Adam", 5), rep("Bob", 10)), 
                 card_id = c(rep("0001", 2), rep("0002", 3), rep("0003", 5), rep("0004", 5)), 
                 bill_date = c("2017-01", "2017-02", 
                               "2017-01", "2017-02", "2017-03", 
                               "2017-01", "2017-02", "2017-03", "2017-05", "2017-06", 
                               "2017-01", "2017-02", "2017-03", "2017-04", "2017-05"), stringsAsFactors = F)

#      id card_id bill_date
# 1  Adam    0001   2017-01
# 2  Adam    0001   2017-02
# 3  Adam    0002   2017-01
# 4  Adam    0002   2017-02
# 5  Adam    0002   2017-03
# 6   Bob    0003   2017-01
# 7   Bob    0003   2017-02
# 8   Bob    0003   2017-03
# 9   Bob    0003   2017-05
# 10  Bob    0003   2017-06
# 11  Bob    0004   2017-01
# 12  Bob    0004   2017-02
# 13  Bob    0004   2017-03
# 14  Bob    0004   2017-04
# 15  Bob    0004   2017-05

我想获取每个card_id的每个id的最大连续账单号。

预期结果:

#      id card_id max_cont_bill_num
# 1  Adam    0001                 2
# 2  Adam    0002                 3
# 3   Bob    0003                 3
# 4   Bob    0004                 5

3 个答案:

答案 0 :(得分:1)

我们可以尝试使用difftimerle。创建一个函数,将'bill_date'转换为Date,分类,获取相邻日期的差,转换为整数,然后获取值的运行长度ID,选择最大值{{1} }。按“ id”,“ card_id”分组后应用该功能

length

答案 1 :(得分:1)

dat %>% mutate(numb=as.integer(gsub("^[0-9]*-","",bill_date))) %>% 
  group_by(id, card_id) %>% summarize(maxc=numb[sum(numb==numb[1]:(numb[n()]+numb[1]-1))])

结果:

# A tibble: 4 x 3
# Groups:   id [?]
  id    card_id  maxc
  <chr> <chr>   <int>
1 Adam  0001        2
2 Adam  0002        3
3 Bob   0003        3
4 Bob   0004        5

说明: mutate创建一个仅包含月份数字的列。 然后,我们将idcard_id进行分组,并创建一个摘要,该摘要将组中数字的向量与从组中第一个月到最后一个月的等长向量进行比较,将所有结果相加答案为“ TRUE”,然后返回行中与该总和相对应的数字(即最后一个连续的数字)。

注意:当bill_date连续跨越一年以上时,这将中断。


好的,我试图思考如何解决跨年度的案例,然后我想出了解决方案。

首先是新数据,其中一个案例跨越两年:

dat = data.frame(id = c(rep("Adam", 5), rep("Bob", 10)), 
                  card_id = c(rep("0001", 2), rep("0002", 3), rep("0003", 5), rep("0004", 5)), 
                  bill_date = c("2017-01", "2017-02", 
                                "2017-12", "2018-01", "2018-03", 
                                "2017-01", "2017-02", "2017-03", "2017-05", "2017-06", 
                                "2017-01", "2017-02", "2017-03", "2017-04", "2017-05"), stringsAsFactors = F)

现在,我们将帐单日期更改为实际日期,并使用cut.POSIXt创建一个月序列,并将先前的解决方案应用于该序列:

dat$monthseq<-cut.POSIXt(as.POSIXct(paste0(dat$bill_date,"-01")),breaks="month",labels=FALSE)
dat%>% 
  group_by(id, card_id) %>% 
  summarize(maxc=bill_date[sum(monthseq==monthseq[1]:(monthseq[n()]))])

结果:

# A tibble: 4 x 3
# Groups:   id [?]
  id    card_id maxc   
  <chr> <chr>   <chr>  
1 Adam  0001    2017-02
2 Adam  0002    2018-01
3 Bob   0003    2017-03
4 Bob   0004    2017-05

答案 2 :(得分:0)

很抱歉,我第一次没有充分阅读OP回答。

library(tidyverse); library(lubridate)
dat %>%
  # new group for each gap in time series or new id / card_id
  mutate(date = ymd(bill_date,truncated = 2),
         gap = id  != lag(id, default = "") | 
           card_id != lag(card_id, default = "") |
              date != lag(date) %m+% months(1),
         group = cumsum(gap)) %>%
  # How many in each group?
  count(id, card_id, group) %>%
  # Just keep each id / card_id's longest streak
  group_by(id, card_id) %>%
  top_n(1, wt = n)