Problem
我有一个大型(> 500e6 行)数据集,已放入 pytables 数据库中。
假设第一列是 ID,第二列是每个 ID 的计数器。每个 ID 计数器组合必须是唯一的。我在尝试查找的 500e6 行中有一个非唯一行。
作为初学者,我做了这样的事情:
index1 = db.cols.id.create_index()
index2 = db.cols.counts.create_index()
for row in db:
query = '(id == %d) & (counts == %d)' % (row['id'], row['counts'])
result = th.readWhere(query)
if len(result) > 1:
print row
我承认这是一种蛮力方法。有什么改进建议吗?
update
当前暴力破解运行时间为 8421 分钟。
solution感谢大家的意见和建议。我使用以下方法设法将运行时间降低到 2364.7 秒:
ex = tb.Expr('(x * 65536) + y', uservars = {"x":th.cols.id, "y":th.cols.counts})
ex = tb.Expr(expr)
ex.setOutput(th.cols.hash)
ex.eval()
indexrows = th.cols.hash.create_csindex(filters=filters)
ref = None
dups = []
for row in th.itersorted(sortby=th.cols.hash):
if row['hash'] == ref:
dups.append(row['hash'] )
ref = row['hash']
print("ids: ", np.right_shift(np.array(dups, dtype=np.int64), 16))
print("counts: ", np.array(dups, dtype=np.int64) & 65536-1)
我可以生成完美的哈希值,因为我的最大值小于 2^16。我有效地将两列打包成 32 位 int。
一旦生成了 csindex,迭代排序值并对重复项进行邻居测试就相当简单了。
这种方法可能可以稍微调整一下,但我正在测试一些可能提供更自然的解决方案的替代方案。