在Python中合并具有数百万行的两个表
我正在使用Python进行一些数据分析。我有两个表,第一个(叫它“ A”)有1000万行和10列,第二个(“
B”)有7300万行和2列。他们有1个具有共同ID的列,我想根据该列将两个表相交。特别是我想要表的内部联接。
我无法将表B作为pandas数据框加载到内存中,以在pandas上使用常规合并功能。我尝试通过读取表B上的文件的块,将每个块与A相交,并将这些交集连接起来(内部联接的输出)。这在速度上还可以,但时不时地给我带来问题,并吐出分段错误……不是很好。很难重现此错误,但是会在两台不同的计算机(Mac
OS X v10.6(Snow Leopard)和UNIX,Red Hat Linux)上发生。
我最终通过将表B写入磁盘,然后遍历表A并从表B中选择匹配的行来尝试使用Pandas和PyTables的组合。最后一个选项有效,但是速度很慢。缺省情况下,已经在pytables的表B上建立了索引。
我该如何解决这个问题?
-
这是一个伪伪鳕鱼,但我认为应该很快。
基于磁盘的直接合并,磁盘上的所有表。关键是您本身并没有做选择,只是通过启动/停止索引到表中,这非常快。
选择满足B中条件的行(使用A的id)不会很快,因为我认为这可能会将数据带入Python空间而不是内核内搜索(我不确定,但是您可能想要在内核优化部分中进一步研究pytables.org。有一种方法可以确定它是否将在内核中。
同样,如果您愿意的话,这是一个非常并行的问题(只是不要将结果从多个进程写入同一文件。pytables对此不安全)。
对于您的merge_a_b操作,我认为您可以使用效率很高的标准pandas连接(在内存中)。
另一种选择(取决于A的大小)可能是将A分成两部分(索引相同),并在第一个表中使用较小的(可能使用单列)。而不是存储合并结果本身,而是存储行索引;之后,您可以提取所需的数据(有点像使用索引器并获取数据)。
A = HDFStore('A.h5') B = HDFStore('B.h5') nrows_a = A.get_storer('df').nrows nrows_b = B.get_storer('df').nrows a_chunk_size = 1000000 b_chunk_size = 1000000 def merge_a_b(a,b): # Function that returns an operation on passed # frames, a and b. # It could be a merge, join, concat, or other operation that # results in a single frame. for a in xrange(int(nrows_a / a_chunk_size) + 1): a_start_i = a * a_chunk_size a_stop_i = min((a + 1) * a_chunk_size, nrows_a) a = A.select('df', start = a_start_i, stop = a_stop_i) for b in xrange(int(nrows_b / b_chunk_size) + 1): b_start_i = b * b_chunk_size b_stop_i = min((b + 1) * b_chunk_size, nrows_b) b = B.select('df', start = b_start_i, stop = b_stop_i) # This is your result store m = merge_a_b(a, b) if len(m): store.append('df_result', m)