用于数千个大表的Python外连接

Par*_*val 7 python numpy python-2.7 pandas

所以,我有大约4,000个CSV文件,我需要外部加入所有这些文件.每个文件有两列(一个字符串和一个浮点数),在10,000-1,000,000行之间,我希望通过第一列(即字符串变量)加入.

我试过了numpy.lib.recfunctions.join_by,但那很痛苦.我切换到了pandas.merge这个速度要快得多,但考虑到我拥有的表的数量(和大小),它仍然太慢了.它似乎真的是内存密集型 - 当合并的文件有数十万行时,机器变得无法使用(我主要使用的是MacBook Pro,2.4GHz,4GB).

所以现在我正在寻找替代方案 - 我还缺少其他潜在的解决方案吗?Python还有哪些其他外连接实现?是否有某个论文/网站讨论并比较每个实施的时间复杂性?如果我只是简单地使用Python调用sqlite3,然后让sqlite3进行连接,那会更有效吗?字符串键是问题吗?如果我可以使用数字键,它应该更快吗?

如果它有助于您更加具体地了解我正在尝试实现的目标,请使用pandas.merge以下代码:

import os
import pandas as pd

def load_and_merge(file_names, path_to_files, columns):
    '''
    seq, str, dict -> pandas.DataFrame
    '''
    output = pd.DataFrame(columns = ['mykey']) # initialize output DataFrame
    for file in file_names:

        # load new data
        new_data = pd.read_csv(path + file,
                               usecols = [col for col in columns.keys()],
                               dtype = columns,
                               names = ['mykey', file.replace('.csv', '')],
                               header = None)

        # merge with previous data
        output = pd.merge(output, new_data, on = 'mykey', how = 'outer')
        output = output.fillna(0) # kill NaNs

    return output

path = '/Users/username/data/'
files_list = [file for file in os.listdir(path) if '.csv' in file]
merged_table = load_and_merge(files_list, path, {0: 'S30', 1: 'float'})
Run Code Online (Sandbox Code Playgroud)

(Mac OS X 10.6.8和Python 2.7.5; Ubuntu 12.04和Python 2.7.3)

Jef*_*eff 7

这是我如何处理这个问题.

不要迭代合并.你正在将一个较小的框架(称为'mergee')与一个较大的框架合并(称之为'合并').然后重复这个,导致'merger'变得更大并且有更多的行.

相反,您可以重复进行分层合并.假设您为合并1-4000编号.

合并1和2以形成1_2

然后重复,然后合并1_2和3_4以形成1_2_3_4

这不会改变你正在做的工作量,但它会使每个合并更简单,这会降低内存障碍和花费的时间(因为它必须通过密钥的笛卡尔积).随机化合并顺序可能是有意义的.

此外,这是完全可并行的,因为您可以让独立的进程处理此问题,从而生成中间合并.这基本上成为map-reduce类型的问题.

您还可以将中间合并存储在HDF5文件中(使用HDFStore),这将使存储非常有效.请注意,这些应该是SEPARATE文件,以避免写入具有多个进程的同一文件(HDF5不支持).