2014-07-25 24 views
0

末考虑形式马克开始和团体

 seller buyer  month 
1: 50536344 61961225 1993-01-01 
2: 50536344 61961225 1993-02-01 
3: 50536344 61961225 1993-04-01 
4: 50536344 61961225 1993-05-01 
5: 50536344 61961225 1993-06-01 

data.table结构,在那里我有(buyer, seller)双随着时间的推移。我想标记每一对的开始和结束。例如,我们看到从一月到二月有一对,三月没有,一到四月到六月。因此,下面的将是所期望的输出:

 seller buyer  month start end 
1: 50536344 61961225 1993-01-01 True False 
2: 50536344 61961225 1993-02-01 False True 
3: 50536344 61961225 1993-04-01 True False 
4: 50536344 61961225 1993-05-01 False False 
5: 50536344 61961225 1993-06-01 False True 

回答

2

假设month处于Date类(或类似地用于POSIXtIDateTime或其他类与diff方法),则可以使用diff函数做到这一点。

# sort data.table 
setkeyv(dt, c("seller", "buyer", "month")) 
# define start 
dt[, start := c(TRUE, diff(month) > 31), by = list(seller, buyer)] 
# define end 
dt[, end := c(diff(month) > 31, TRUE), by = list(seller, buyer)] 

编辑:@David Arenburg的建议:你当然可以一次性定义开始和结束。这应该稍微快一点,但我也觉得它更难读。

dt[, ":=" (start = c(TRUE, diff(month) > 31), 
      end = c(diff(month) > 31, TRUE)), 
    by = list(seller, buyer)] 

EDIT2:发生了什么事的一些更explonation:每对卖方和买方先观察将永远是一个商业关系的开始,所以start = c(TRUE, ...)。之后,如果且仅当时间差超过一个月(31天)时,进一步观察业务关系才会开始,所以diff(month) > 31。把这两件事放在一起,你得到c(TRUE, diff(month) > 31)。 一个类似的逻辑适用于最后,你必须比较下一个观察,而不是前一个观察。

+0

为什么你需要假设'Date'类?只需使用'data.table'中的'IDateTime',即:'dt [,start:= c(TRUE,diff(as.IDate(month))> 31),by = list(seller,buyer)]; dt [,end:= c(diff(as.IDate(month))> 31,TRUE),by = list(seller,buyer)]' –

+0

@David Arenburg:当然,'IDateTime'也可以,日期类(使用“diff”方法)而不是“字符”或“因素”。 – shadow

+0

另外,为什么不能一气呵成呢?结束= c(差异(as.IDate(月))> 31,TRUE)),by(由于.IDate(月))> =清单(卖方,买方)]'。 (在':='后面加上反引号)。除此之外(+1):) –