[英]Summarizing huge amounts of data
我有一個問題,我無法解決。 我有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)
)。 但是,為了做到這一點,文件必須為每個字母迭代一次,這對於文件大小(max = 69GB)是不可信的。 也許在迭代文件時,可以打開一個pickle並將條目保存在dict中,然后關閉pickle。 但是,由於打開,加載和關閉pickle文件所需的時間,為每個項目執行此操作會使進程大大減慢。
解決此問題的一種方法是在一次傳遞期間對所有條目進行排序,然后迭代排序的文件並按字母順序計算條目。 但是,即使使用linux命令對文件進行排序也非常慢:
sort file.txt > sorted_file.txt
並且,我真的不知道如何使用python解決這個問題,因為將整個文件加載到內存中進行排序會導致內存錯誤。 我對不同的排序算法有一些膚淺的了解,但是它們似乎都要求整個待排序的對象需要加載到內存中。
任何有關如何處理此問題的提示都將非常感激。
我一直在考慮保存以單獨文件中的某些字母開頭的條目,即以a開頭的所有條目都保存在a.txt中,依此類推(這應該可以使用defaultdic(int))。 但是,為了做到這一點,文件必須為每個字母迭代一次,這對於文件大小(max = 69GB)是不可信的。
你幾乎就是這種思路。 你想要做的是根據前綴分割文件 - 你不必為每個字母迭代一次。 這在awk中是微不足道的。 假設您的輸入文件位於名為input
的目錄中:
mkdir output
awk '/./ {print $0 > ( "output/" substr($0,0,1))}` input/*
這會將每一行追加到以該行的第一個字符命名的文件中(注意如果你的行可以以空格開頭,這將是奇怪的;因為這些是ngram,我認為這是不相關的)。 您也可以在Python中執行此操作,但管理文件的打開和關閉有點繁瑣。
由於文件已被拆分,因此它們現在應該小得多。 您可以對它們進行排序,但實際上並不需要 - 您可以單獨讀取文件並使用以下代碼獲取計數:
from collections import Counter
ngrams = Counter()
for line in open(filename):
ngrams[line.strip()] += 1
for key, val in ngrams.items():
print(key, val, sep='\t')
如果文件仍然太大,您可以增加用於存儲行的前綴的長度,直到文件足夠小。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.