所以,我有大约 4,000 个 CSV 文件,我需要对所有这些文件进行外部联接。每个文件有两列(一个字符串和一个 float )和 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'})
(Mac OS X 10.6.8 和 Python 2.7.5;Ubuntu 12.04 和 Python 2.7.3)
最佳答案
下面是我将如何解决这个问题。
不要迭代合并。您正在将一个较小的框架(称为“合并”)与一个较大的框架(称为“合并”)合并。然后重复此操作,导致“合并”变得更大并具有更多行。
相反,您可以进行重复的分层合并。假设您将 mergees 编号为 1-4000。
合并 1 和 2 形成 1_2
然后重复,然后合并 1_2 和 3_4 形成 1_2_3_4
这不会改变您正在做的工作量,但它使每次合并变得更加简单,从而降低了内存障碍和花费的时间(因为它必须通过键的笛卡尔积)。随机化合并顺序可能是有意义的。
此外,这是完全可并行化的,因为您可以让独立进程处理此问题,生成中间合并。这实质上变成了 map-reduce 类型的问题。
您还可以将中间合并存储在 HDF5 文件中(使用 HDFStore
),这将使存储非常高效。请注意,这些应该是单独的文件,以避免使用多个进程写入同一文件(HDF5 不支持)。
关于python - 在 Python 中为数千个大表进行外部连接,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19452653/