這裏是一個data.table
辦法(大致相同@ josilber從plyr
的):
pairs <- dat[, c(id=split(combn(id,2),1:2)), by=group ]
pairs[, .N, by=.(id.1,id.2) ]
# id.1 id.2 N
# 1: 10 11 2
# 2: 10 12 1
# 3: 11 12 1
# 4: 10 13 1
# 5: 11 13 2
你也可以考慮觀看的table
結果:
pairs[, table(id.1,id.2) ]
# id.2
# id.1 11 12 13
# 10 2 1 1
# 11 0 1 2
可以使用融合,而不是combn
:
setkey(dat, group)
dat[ dat, allow.cartesian=TRUE ][ id<i.id, .N, by=.(id,i.id) ]
基準。對於大數據,合併可能會更快一些(正如@DavidArenburg所假設的那樣)。 @阿倫的回答是快還是:
DT <- data.table(g=1,id=1:(1.5e3),key="id")
system.time({a <- combn(DT$id,2)})
# user system elapsed
# 0.81 0.00 0.81
system.time({b <- DT[DT,allow.cartesian=TRUE][id<i.id]})
# user system elapsed
# 0.13 0.00 0.12
system.time({d <- DT[,.(rep(id,(.N-1L):0L),id[indices(.N-1L)])]})
# user system elapsed
# 0.01 0.00 0.02
(我離開了集團,通過操作,因爲我不認爲這將是對時序非常重要的。)
在combn的防禦。的combn
辦法很好地擴展到更大的連擊,而合併和@阿倫的回答,而更快的對,不(據我可以看到):
DT2 <- data.table(g=rep(1:2,each=5),id=1:5)
tuple_size <- 4
tuples <- DT2[, c(id=split(combn(id,tuple_size),1:tuple_size)), by=g ]
tuples[, .N, by=setdiff(names(tuples),"g")]
# id.1 id.2 id.3 id.4 N
# 1: 1 2 3 4 2
# 2: 1 2 3 5 2
# 3: 1 2 4 5 2
# 4: 1 3 4 5 2
# 5: 2 3 4 5 2
其實我最喜歡的最後一種方法。爲什麼不推薦? –
@DavidArenburg我想像做這樣的笛卡爾連接是非常緩慢的。此外,它僅適用於特殊情況下的對,而'c(id = split(combn(id,3),1:3))'是第一種方法的直接擴展。最後,在這裏導航'i。*'符號有點繁瑣,導致結果中出現「錯誤」的名字。 – Frank
我不認爲二進制連接會很慢,但由於是笛卡爾連接,可能會花費一些額外的內存。 –