【发布时间】:2018-12-10 11:27:39
【问题描述】:
我有一个我无法解决的问题。我有 4 个.txt 文件,每个文件在 30-70GB 之间。每个文件包含如下 n-gram 条目:
blabla1/blabla2/blabla3
word1/word2/word3
...
我要做的是计算每个项目出现的次数,并将这些数据保存到一个新文件中,例如:
blabla1/blabla2/blabla3 : 1
word1/word2/word3 : 3
...
到目前为止,我的尝试只是将所有条目保存在字典中并计算它们,即
entry_count_dict = defaultdict(int)
with open(file) as f:
for line in f:
entry_count_dict[line] += 1
但是,使用这种方法时会遇到内存错误(我有 8GB RAM 可用)。数据遵循 zipfian 分布,例如大多数项目只出现一次或两次。 条目总数尚不清楚,但(非常)粗略估计总共有大约 15,000,000 个条目。
除此之外,我还尝试了h5py,其中所有条目都保存为包含数组[1] 的h5py 数据集,然后更新,例如:
import h5py
import numpy as np
entry_count_dict = h5py.File(filename)
with open(file) as f:
for line in f:
if line in entry_count_dict:
entry_count_file[line][0] += 1
else:
entry_count_file.create_dataset(line,
data=np.array([1]),
compression="lzf")
但是,这种方法速度很慢。写入速度越来越慢。因此,除非可以提高写入速度,否则这种方法是不可信的。此外,以块的形式处理数据并为每个块打开/关闭 h5py 文件并没有显示出处理速度的任何显着差异。
我一直在考虑将以某些字母开头的条目保存在单独的文件中,即所有以a 开头的条目都保存在a.txt 中,依此类推(这应该可以使用defaultdic(int)) .
但是,要做到这一点,文件必须为每个字母迭代一次,考虑到文件大小(最大 = 69GB),这是不可信的。
也许在遍历文件时,可以打开泡菜并将条目保存在字典中,然后关闭泡菜。但是,由于打开、加载和关闭 pickle 文件需要时间,因此对每个项目执行此操作会大大减慢该过程。
解决此问题的一种方法是在一次遍历中对所有条目进行排序,然后遍历排序的文件并按字母顺序计算条目。但是,即使使用 linux 命令对文件进行排序也会非常缓慢:
sort file.txt > sorted_file.txt
而且,我真的不知道如何使用 python 解决这个问题,因为将整个文件加载到内存中进行排序会导致内存错误。我对不同的排序算法有一些肤浅的了解,但是它们似乎都要求将要排序的整个对象加载到内存中。
任何有关如何解决此问题的提示将不胜感激。
【问题讨论】:
-
我认为你想出的任何 Python 解决方案都不会比
sort ngrams.txt | uniq -c更快,所以坚持下去 -
python 中有几个可用的模块可用于实现字典,其中条目保存或缓存在磁盘而不是内存中。以this question 为例。还要考虑google searching for key/value stores 并寻找一些适合您需要的内容,即只要它适合内存就可以在内存中完成大部分工作,但当您的“字典”太大而无法放入内存时使用磁盘。
标签: python python-3.x nlp hdf5 large-data