我有一个这样的数据库:
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
答案 0 :(得分:1)
我们可以尝试使用difftime
和rle
。创建一个函数,将'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
创建一个仅包含月份数字的列。
然后,我们将id
和card_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)