假设我有一个 data.table,其中包含一个 id 以及其他四列整数值。如何高效地找到在这四个其他列中至少有两个值相同的行?
第二种方法是使用data.table并对表的长格式进行操作。这种方法更易于维护(不需要硬编码所有组合),但速度较慢:
有没有一种方法可以在不硬编码所有检查组合的情况下获取第一个(宽)解决方案的速度?
对于我的实际表,N是可管理的(~3M),但足够大以感受到第二个解决方案中的操作负担。
fooTbl = data.table(id = c('a', 'b'), ind1=c(1,2), ind2=c(3,4), ind3=c(2,3), ind4=c(2,1))
fooTbl
# id ind1 ind2 ind3 ind4
# 1: a 1 3 2 2
# 2: b 2 4 3 1
我已经有两个解决方案了。第一个比第二个快得多,但第一个需要硬编码所有组合并检查它们的相等性。这似乎是不可取的,并且随着列数的增加,维护起来也很困难:
fooTbl[, uniq := (ind1 != ind2 & ind1 != ind3 & ind1 != ind4 & ind2 != ind3 & ind2 != ind4 & ind3 != ind4)]
fooTbl
# id ind1 ind2 ind3 ind4 uniq
# 1: a 1 3 2 2 FALSE
# 2: b 2 4 3 1 TRUE
第二种方法是使用data.table并对表的长格式进行操作。这种方法更易于维护(不需要硬编码所有组合),但速度较慢:
fooTbl[, uniq := NULL]
fooTbl
# id ind1 ind2 ind3 ind4
# 1: a 1 3 2 2
# 2: b 2 4 3 1
fooTbl = melt(fooTbl, measure=c('ind1', 'ind2', 'ind3', 'ind4'))
fooTbl
# id variable value
# 1: a ind1 1
# 2: b ind1 2
# 3: a ind2 3
# 4: b ind2 4
# 5: a ind3 2
# 6: b ind3 3
# 7: a ind4 2
# 8: b ind4 1
fooTbl[, N := length(unique(value)), by=id]
fooTbl[, uniq := N == 4][, N := NULL]
fooTbl
id variable value uniq
1: a ind1 1 FALSE
2: b ind1 2 TRUE
3: a ind2 3 FALSE
4: b ind2 4 TRUE
5: a ind3 2 FALSE
6: b ind3 3 TRUE
7: a ind4 2 FALSE
8: b ind4 1 TRUE
fooTbl = dcast(fooTbl, id + uniq ~ variable, value.var='value')
fooTbl
id uniq ind1 ind2 ind3 ind4
1 a FALSE 1 3 2 2
2 b TRUE 2 4 3 1
有没有一种方法可以在不硬编码所有检查组合的情况下获取第一个(宽)解决方案的速度?
对于我的实际表,N是可管理的(~3M),但足够大以感受到第二个解决方案中的操作负担。