首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >总结海量数据

总结海量数据
EN

Stack Overflow用户
提问于 2018-07-02 17:17:01
回答 2查看 115关注 0票数 3

我有一个我还没能解决的问题。我有4个.txt文件,每个在30-70 30之间。每个文件包含如下n元语法条目:

代码语言:javascript
运行
复制
blabla1/blabla2/blabla3
word1/word2/word3
...

我要做的是计算每一项出现的次数,并将这些数据保存到一个新文件中,例如:

代码语言:javascript
运行
复制
blabla1/blabla2/blabla3  : 1
word1/word2/word3        : 3
...

到目前为止,我的尝试只是保存字典中的所有条目并对它们进行计数,即

代码语言:javascript
运行
复制
entry_count_dict = defaultdict(int)
with open(file) as f:
    for line in f:
        entry_count_dict[line] += 1

然而,使用这种方法我遇到了内存错误(我有8 8GB的RAM可用)。数据遵循zipfian分布,例如,大多数项目只出现一次或两次。条目总数尚不清楚,但粗略估计大约有15,000,000个条目。

除此之外,我还尝试了h5py,其中所有条目都保存为包含数组[1]的h5py数据集,然后对其进行更新,例如:

代码语言:javascript
运行
复制
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 =69 is ),这是不可信的。也许在迭代文件时,可以打开一个pickle并将条目保存在字典中,然后关闭该pickle。但是,由于打开、加载和关闭pickle文件所需的时间较长,因此为每个项目执行此操作会大大减慢进程。

解决这个问题的一种方法是在一次遍历中对所有条目进行排序,然后迭代排序后的文件并按字母顺序对条目进行计数。但是,即使使用linux命令对文件进行排序也会非常慢:

sort file.txt > sorted_file.txt

而且,我真的不知道如何使用python来解决这个问题,因为将整个文件加载到内存中进行排序会导致内存错误。我对不同的排序算法有一些肤浅的了解,但是它们似乎都需要将要排序的整个对象加载到内存中。

任何关于如何接近这一点的技巧都将非常感谢。

EN

回答 2

Stack Overflow用户

发布于 2018-07-02 18:15:15

有许多算法可以执行这种类型的操作。它们都属于External Sorting的一般标题。

您在其中所做的“将以某些字母开头的条目保存在单独的文件中”实际上被称为存储桶排序,从理论上讲,它应该更快。在切片数据集上尝试它。

或者,试试Dask,这是一个由DARPA + Anaconda支持的分布式计算库,它的接口与numpy、pandas相似,其工作方式类似于Apache-Spark。(也可以在单机上运行)顺便说一句,它可以扩展

我建议尝试dask.array,它将大数组分成许多小数组,并使用阻塞算法实现numpy ndarray接口,以便在计算这些大于内存的数据时利用所有内核。

票数 0
EN

Stack Overflow用户

发布于 2018-07-04 11:45:15

我一直在考虑将以某些字母开头的条目保存在单独的文件中,即所有以a开头的条目都保存在a.txt中,依此类推(这应该可以使用defaultdic(int))。然而,要做到这一点,文件必须为每个字母迭代一次,考虑到文件大小(max =69 is ),这是不可信的。

有了这样的思路,你就快到了。您要做的是根据前缀拆分文件-您不必为每个字母迭代一次。这在awk中是微不足道的。假设您的输入文件位于一个名为input的目录中

代码语言:javascript
运行
复制
mkdir output
awk '/./ {print $0 > ( "output/"  substr($0,0,1))}` input/*

这会将每一行附加到以该行的第一个字符命名的文件中(注意,如果您的行可以以空格开头,这会很奇怪;因为这些是ngram,我假设这是不相关的)。您也可以在Python中做到这一点,但是管理文件的打开和关闭有点单调乏味。

因为文件已经被拆分了,所以它们现在应该更小了。你可以对它们进行排序,但真的没有必要--你可以逐个读取这些文件,并使用如下代码获得计数:

代码语言:javascript
运行
复制
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')

如果文件仍然太大,您可以增加用于存储行的前缀的长度,直到文件足够小。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/51132716

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档