2015-12-22 46 views
1

我有数据框df,包括客户名称,加入日期,到期日和队列。R中的队列数据转换

names   dj  exp cohort 
    (fctr)  (date)  (date) (chr) 
1 Tom 2011-05-01 2011-06-22 2011-05 
2 David 2011-06-01 2011-07-19 2011-06 
3 Jack 2011-05-03 2012-01-03 2011-05 
> 

names<-c("Tom","David","Jack") 
dj<-as.Date(c("2011-05-01","2011-06-01","2011-05-03")) 
exp<-as.Date(c("2011-06-22","2011-07-19","2012-01-03")) 
df<-data.frame(names,dj,exp) 
df$cohort<-format(df$dj,"%Y-%m") 
tbl_df(df) 

和矢量DateColumns <- seq.Date(as.Date("2011/05/01"), as.Date("2015/12/1"), by = "1 month")自2011年5月1日的日历日期2015年12月1日

从中我想检查客户是否在特定月份或不活跃。活动定义为一个客户记录> DateColumns & DJ < = DateColumns

输出1(正确):

names dj exp cohort    2011-05-01 2011-06-01 2011-07-01 2011-08-01 . 

Tom 2011-05-01 2011-06-22 2011-05 TRUE  TRUE  FALSE  FALSE 
David 2011-06-01 2011-07-19 2011-06 FALSE  TRUE  TRUE  FALSE 
Jack 2011-05-03 2012-01-03 2011-05 TRUE  TRUE  TRUE  TRUE .... 

下面是我写的代码,可惜这无法与比较两者到期日和DJ日期栏中的日历日期。例如,大卫在X1中应该是虚假的。那么,我该怎么做?

不正确的输出

names<-c("Tom","David","Jack") 
    dj<-as.Date(c("2011-05-01","2011-06-01","2011-05-03")) 
    exp<-as.Date(c("2011-06-22","2011-07-19","2012-01-03")) 
    df<-data.frame(names,dj,exp) 
    df$cohort<-format(df$dj,"%Y-%m") 


    DateColumns <- seq.Date(as.Date("2011/05/01"), as.Date("2015/12/1"), by = "1 month") 

DateColumnvalues <- t(sapply(df$exp, function(x) x > DateColumns)) 
df2 <- data.frame(df,DateColumnvalues) 
tbl_df(df2) 

output: 
names   dj  exp cohort X1 X2 X3 X4 X5 X6 
    (fctr)  (date)  (date) (chr) (lgl) (lgl) (lgl) (lgl) (lgl) (lgl) 
1 Tom 2011-05-01 2011-06-22 2011-05 TRUE TRUE FALSE FALSE FALSE FALSE 
2 David 2011-06-01 2011-07-19 2011-06 **TRUE** TRUE TRUE FALSE FALSE FALSE 
3 Jack 2011-05-03 2012-01-03 2011-05 TRUE TRUE TRUE TRUE TRUE TRUE 
Variables not shown: X7 (lgl), X8 (lgl), X9 (lgl), X10 (lgl), X11 (lgl), 
    X12 (lgl), X13 (lgl), X14 (lgl), X15 (lgl), X16 (lgl), X17 (lgl), X18 
    (lgl), X19 (lgl), X20 (lgl), X21 (lgl), X22 (lgl), X23 (lgl), X24 (lgl), 
    X25 (lgl), X26 (lgl), X27 (lgl), X28 (lgl), X29 (lgl), X30 (lgl), X31 
    (lgl), X32 (lgl), X33 (lgl), X34 (lgl), X35 (lgl), X36 (lgl), X37 (lgl), 
    X38 (lgl), X39 (lgl), X40 (lgl), X41 (lgl), X42 (lgl), X43 (lgl), X44 
    (lgl), X45 (lgl), X46 (lgl), X47 (lgl), X48 (lgl), X49 (lgl), X50 (lgl), 
    X51 (lgl), X52 (lgl), X53 (lgl), X54 (lgl), X55 (lgl), X56 (lgl) 
> 

注:X1是 “2011-05-01” 和X2 = “2011-06-01” 等表示日历月

其次,我想要改造这个数据“相对”基于加入和队列的月份进行汇总。例如,如果客户“迪克”于2015年1月加入,并且将于2015年12月到期,则他的M0应设为真,但M0应视为2015年1月而非日历月。

Names dj exp cohort      M0 M1 M2 M3 till M55 
Dick 2015-01-11 2015-12-10 2015-01  T T T T 
Tom 2011-05-01 2011-06-22 2011-05  T T F F 
David 2011-06-01 2011-07-19 2011-06  T T F F 

回答

1

作为回答第一个问题,你可以做

library(data.table) 
library(lubridate) 
dt <- data.table(df, key=c("dj", "exp")) 
dates <- setDT(transform(data.frame(start = seq.Date(as.Date("2011-05-01"), as.Date("2011-08-01"), "1 month")), 
            end = start + months(1) - 1), 
       key = c("start", "end")) 
dcast(foverlaps(dt, dates)[, val:=TRUE], names+dj+exp+cohort~start, value.var="val", fill=FALSE) 
# names   dj  exp cohort 2011-05-01 2011-06-01 2011-07-01 2011-08-01 
# 1: David 2011-06-01 2011-07-19 2011-06  FALSE  TRUE  TRUE  FALSE 
# 2: Jack 2011-05-03 2012-01-03 2011-05  TRUE  TRUE  TRUE  TRUE 
# 3: Tom 2011-05-01 2011-06-22 2011-05  TRUE  TRUE  FALSE  FALSE 

关于第二个问题,如果我理解正确的话,我会跟去

lst <- apply(df[2:3], 1, function(x) { x <- as.Date(x); as.logical(seq_along(seq(x[1], x[2], by="month"))) }) 
n <- max(lengths(lst)) 
res <- cbind(df, do.call(rbind, lapply(lst, function(x) `length<-`(x, n)))) 
res[is.na(res)] <- FALSE; res 
# names   dj  exp cohort 1 2  3  4  5  6  7  8  9 
# 1 Tom 2011-05-01 2011-06-22 2011-05 TRUE TRUE FALSE FALSE FALSE FALSE FALSE FALSE FALSE 
# 2 David 2011-06-01 2011-07-19 2011-06 TRUE TRUE FALSE FALSE FALSE FALSE FALSE FALSE FALSE 
# 3 Jack 2011-05-03 2012-01-03 2011-05 TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE 
+0

嗨卢克谢谢。第二个查询是关于汇总加入月数的每个人。说M0是加入的月份,M1是加入的1个月,m2是加入的第二个月。 –

+0

第二个代码中的插孔卢克数据不正确 –

+0

此外,如果不是非常适合队列分析,因为它没有涵盖每个月的月份范围......无论如何,你是否在寻找“res” ?如果你想要55个月,你可能想要改变'n <-55 ... – lukeA