在Python中合并具有数百万行的两个表

发布于 2021-01-29 18:14:14

我正在使用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上建立了索引。

我该如何解决这个问题?

关注者
0
被浏览
183
1 个回答
  • 面试哥
    面试哥 2021-01-29
    为面试而生,有面试问题,就找面试哥。

    这是一个伪伪鳕鱼,但我认为应该很快。

    基于磁盘的直接合并,磁盘上的所有表。关键是您本身并没有做选择,只是通过启动/停止索引到表中,这非常快。

    选择满足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)
    


知识点
面圈网VIP题库

面圈网VIP题库全新上线,海量真题题库资源。 90大类考试,超10万份考试真题开放下载啦

去下载看看