比较python中两个巨大的csv文件的最快方法(numpy)

时间:2017-06-08 23:34:17

标签: python pandas csv numpy bigdata

我正在尝试找到两个相当大的csv文件之间的intesect子集 电话号码(一个有600k行,另一个有300mil)。我目前正在使用pandas打开两个文件,然后将所需的列转换为1d numpy数组,然后使用numpy intersect来获取相交。有没有更好的方法来做到这一点,使用python或任何其他方法。谢谢你的帮助

import pandas as pd
import numpy as np

df_dnc = pd.read_csv('dncTest.csv', names = ['phone'])
df_test = pd.read_csv('phoneTest.csv', names = ['phone'])

dnc_phone = df_dnc['phone']
test_phone = df_test['phone']

np.intersect1d(dnc_phone, test_phone)

2 个答案:

答案 0 :(得分:3)

我将为您提供一些Python伪代码的一般解决方案。你在这里要解决的是书"Programming Pearls" by Jon Bentley中的经典问题。

只需一个简单的位数组就可以非常高效地解决这个问题,因此我的评论是,电话号码有多长(有多少位数)。

我们假设电话号码最多为10位数,而不是您可以拥有的最大电话号码:9 999 999 999(空格用于提高可读性)。在这里,我们可以使用每个数字1比特来识别数字是否在设置中(比特是否分别设置),因此我们将使用9 999 999 999比特来识别每个数字,即:

  • bits[0]标识号码0 000 000 000
  • bits[193]标识号码0 000 000 193
  • 编号为659 234-4567的问题将由bits[6592344567]
  • 解决

这样做我们需要预先分配最初设置为9 999 999 999的{​​{1}}位,即:0 =大约1.2 GB的内存。

我认为在末尾保持数字的交集将使用比位表示更多的空间=>最多600k整数将被存储=> 9 999 999 999 / 8 / 1024 / 1024 =大约4.6 GB(actually int is not stored that efficiently and might use much more),如果这些是字符串,那么您可能会以更多的内存需求结束。

从CSV文件(逐行或缓冲文件阅读器)解析电话号码字符串,将其转换为数字而不是进行常量时间内存查找将比处理字符串并合并它们更快。不幸的是,我没有这些电话号码文件可以测试,但是有兴趣听听你的发现。

64bit * 600k

我使用了来自bitstring pip packagefrom bitstring import BitArray max_number = 9999999999 found_phone_numbers = BitArray(length=max_number+1) # replace this function with the file open function and retrieving # the next found phone number def number_from_file_iteator(dummy_data): for number in dummy_data: yield number def calculate_intersect(): # should be open a file1 and getting the generator with numbers from it # we use dummy data here for number in number_from_file_iteator([1, 25, 77, 224322323, 8292, 1232422]): found_phone_numbers[number] = True # open second file and check if the number is there for number in number_from_file_iteator([4, 24, 224322323, 1232422, max_number]): if found_phone_numbers[number]: yield number number_intersection = set(calculate_intersect()) print number_intersection ,它需要大约2秒来初始化整个bitstring。之后,扫描文件将使用常量内存。最后,我使用BitArray来存储项目。

注1:可以修改此算法以仅使用set。在这种情况下,只要位数与该位匹配,就必须重置第二个循环,以使重复项不再匹配。

注2:list / set中存储会发生延迟,因为我们在第二个for循环中使用了生成器。运行时复杂性是线性的,即list

答案 1 :(得分:1)

  1. 将600k电话号码读入set
  2. 逐行输入较大的文件,根据集合检查每一行。
  3. 立即将匹配项写入输出文件。
  4. 这样您就不必一次将所有数据加载到内存中。