仅使用每个ID从两列创建对

时间:2015-10-29 06:19:28

标签: r data.table

我有两个id的对列表:(ida,idb)。 我想从这个列表中构建一个“唯一对”列表,意思是每个id(ida和idb)只使用一次。

ida的某些元素可能与idb的任何元素都不匹配。但是必须保留idb的所有元素(如下例中的第6行和第6行)。

这意味着解决方案的最终对的数量应该等于idb的唯一元素的数量。

有时可能有多种解决方案,我只需要其中一种。

dt1 = data.table(ida = c(7,7,8,8,15,16,17,18,19,19,20), idb = c(2,1,2,1,4,5,5,6,7,8,8))
ida idb
1:   7   2
2:   7   1
3:   8   2
4:   8   1
5:  15   4
6:  16   5
7:  17   5
8:  18   6
9:  19   7
10:  19   8
11:  20   8

收率:

 ida idb
1:   7   2
2:   8   1
3:  15   4
4:  16   5
5:  18   6
6:  19   7
7:  20   8

或者:

ida idb
1:   7   1
2:   8   2
3:  15   4
4:  17   5
5:  18   6
6:  19   7
7:  20   8

我们有nrow(result)== length(unique(dt1 $ idb))。当然长度(唯一(结果$ ida))== length(唯一(结果$ idb))。

注意:在第一个解决方案中,元素17已从ida中删除。这是一种预期的行为:不可能同时将16和17链接到5,因为5必须是唯一的。

1 个答案:

答案 0 :(得分:0)

我是以自己的方式做到的,这有点慢,但有效:

my_rows = NULL
sets = dt[, .(ida, idb)]
my_rows = sets[!duplicated(idb) & !duplicated(idb, fromLast = TRUE)]
sets = sets[!ida %in% my_rows$ida]

setkey(sets, idb)
for (idb in unique(sets$idb)) {
    elem = sets[J(idb)]
    my_rows = rbind(my_rows, elem[1])
    sets = sets[ida != elem$ida[1]]
}

随意张贴更短的&如果你有更快的答案!