2014-12-03 91 views
1

考虑一个data.table,其中包含id1,id2几年的匹配。连续行数

 id1 year  id2 
1: 51557094 2003 65122111 
2: 51557094 2004 65122111 
3: 51557094 2005 65122111 
4: 51557094 2007 65122111 
5: 51557094 2008 65122111 
6: 51557093 2006 65122111 

对于这些比赛,我想找出时间,随着比赛开始的一年在一起。如果没有特定年份的数据,则比赛结束(并且在下一年,如果再次有数据,则开始新的比赛)。

因此,对于上面的样本数据,预期产量将

 id1 year  id2 length 
1: 51557094 2003 65122111  3 
2: 51557094 2007 65122111  2 
3: 51557093 2006 65122111  1 

我接受的答案之一,因为它给我带来的远远不够,但是请注意,这是不正确的。虽然它的工作对样本数据,也不会为下列

> dtId 
     id1 year  id2 
1: 51557094 2003 65122111 
2: 51557094 2004 65122111 
3: 51557094 2005 65122111 
4: 51557094 2007 65122111 
5: 51557094 2008 65122111 
6: 51557094 2006 65122112 

> setkey(dtId, id1, id2, year) 
> dtId[,grp := cumsum(c(1,diff(year)) > 1),by=id1] 
> dtId[,list(year=year[1],length=length(year)),by=list(id1,id2,grp)] 
     id1  id2 grp year length 
1: 51557094 65122111 0 2003  5 
2: 51557094 65122112 0 2006  1 

相反,从而导致了在这两个id1, id2比赛变量grp解决了这个问题:

> dtId[,grp := cumsum(c(1,diff(year)) > 1),by=list(id1, id2)] 
> dtId[,list(year=year[1],length=length(year)),by=list(id1,id2,grp)] 
     id1  id2 grp year length 
1: 51557094 65122111 0 2003  3 
2: 51557094 65122112 0 2006  1 
3: 51557094 65122111 1 2007  2 

回答

3

尝试:

dat[,grp := cumsum(c(1,diff(year)) > 1),by=list(id1,id2)] 
dat[,list(year=year[1],length=length(year)),by=list(id1,id2,grp)] 

#  id1  id2 grp year length 
#1: 51557094 65122111 0 2003  3 
#2: 51557094 65122111 1 2007  2 
#3: 51557093 65122111 0 2006  1 
+1

我接受了您的答案,但请注意您可能需要修复它(请参阅更新后的问题)。 – FooBar 2014-12-04 16:50:28

1

首先,我们来制作你的表格

library(data.table) 
dtId <- data.table(
    id1 = c(rep(51557094, 5), 51557093), 
    year = c(2000 + c(3, 4, 5, 7, 8, 6)), 
    id2 = rep(65122111, 6) 
) 

我们可以对它进行排序,并添加一个“newMatch”列,如果新匹配开始,则为TRUE,即与上一行相比,年份没有增加1。

dtId <- dtId[order(id1, id2, year)] 
dtId[, newMatch := c(FALSE, year[-1] != year[-.N] + 1)] 

现在我们可以添加一个“匹配”列,它的值是匹配ID,我们可以聚合。

dtId[, match := cumsum(newMatch)] 
dtAggr <- dtId[ 
    , list(year = min(year), length = .N), 
    by = c("id1", "id2", "match") 
    ] 

删除“匹配”列我们有预期的结果。

dtAggr[, match := NULL] 
dtAggr