最低对序列组合数据表

时间:2016-12-15 12:56:11

标签: r data.table combinations

我有一个有两列的集合。行是值对(a,b)。

require(data.table)        
dt<-data.table(a=c(1,11,11,2,7,5,6), b = c(2,9,8,6,5,3,3))  

我想为每对值分配最小的数字。 但如果其中一个值再次出现在新行中,则必须再次将其与新对比较并选择历史记录中的最低值。结果必须是这个:

res.dt<-data.table(a=c(1,11,11,2,7,5,6), b = c(2,9,8,6,5,3,3), res=c(1,9,8,1,5,3,1))        

    a b res
1:  1 2   1
2: 11 9   9
3: 11 8   8
4:  2 6   1
5:  7 5   5
6:  5 3   3
7:  6 3   1

1 个答案:

答案 0 :(得分:1)

以不同的方式陈述问题:对于每一行 i ,我们需要迭代地更新{em> j 行中最小值的res > i 其中(a_i,b_i)和(a_j,b_j)具有非空交集。

我们可以使用data.table中的non-equi joins(v&gt; = 1.9.8)有效地执行此操作,但由于此功能仅允许单元素比较(>,{{1} },>===<=),我们需要通过比较(a_i,a_j),(a_i,b_j),(b_i,a_j),(b_i, b_j)分开。 (如果这些对中至少有一个包含相同的元素,则存在交集。)迭代地执行此操作会考虑整个历史记录,并且我们可以在结果收敛时停止:

<

结果:

dt[, `:=`(idx=.I, res=pmin(a,b), prev_res=NA)]

while (dt[, !identical(res, prev_res)]) {
  dt[, prev_res:= res]

  # Use non-equi joins to update 'res' for intersecting pairs downstream
  dt[dt[, .(i.a=a, i.res=res, i=.I)], on=.(a==i.a, idx > i), res:= pmin(res, i.res)]

  dt[dt[, .(i.a=a, i.res=res, i=.I)], on=.(b==i.a, idx > i), res:= pmin(res, i.res)]

  dt[dt[, .(i.b=b, i.res=res, i=.I)], on=.(a==i.b, idx > i), res:= pmin(res, i.res)]

  dt[dt[, .(i.b=b, i.res=res, i=.I)], on=.(b==i.b, idx > i), res:= pmin(res, i.res)]

}