用于大型数据集的 Python defaultdict

Posted

技术标签:

【中文标题】用于大型数据集的 Python defaultdict【英文标题】:Python defaultdict for large data sets 【发布时间】:2014-09-26 07:07:59 【问题描述】:

我使用defaultdict 来存储数百万个短语,所以我的数据结构看起来像mydict['string'] = set(['other', 'strings'])。它似乎适用于较小的集合,但是当我按下任何超过 1000 万个键时,我的程序就会崩溃,并显示 Process killed 的有用消息。我知道defaultdicts 内存很重,但是是否有使用defaultdicts 进行存储的优化方法,或者我是否必须查看其他数据结构,例如 numpy 数组?

谢谢

【问题讨论】:

numpy 数组而不是 defaultdict?而不是设置?我不知道这对于第一种情况如何工作,或者在第二种情况下你会如何做得更好——对于类似集合的操作,集合将比 numpy 数组快得多。 无论你获得多少内存减少,当你达到 2000 万个键(或 30M 等)时,都会再次爆炸。将所有内容都保存在核心中确实很方便,但您可能会超出核心。如果您将存储移动到适当的 DBMS,您或您的继任者将来会减少对您的恨意。 感谢您的回复,我意识到我想回复如何处理这个问题。这个大数据集是用来查找较小数据集的,我可以颠倒逻辑。否则 DBMS 会是更好的解决方案 也许可以尝试一下(我不认为这些在标准库中,但是有很多可用的实现)?但前提是您的字典键之间存在显着重叠。集合的开销可能类似于字典 - 如果您的成员很少,可以尝试用元组替换它们。 只需使用 SQLite 数据库。它会为你省去很多痛苦。 【参考方案1】:

如果您打算使用单个 Python 进程留在内存中,那么您将不得不放弃 dict 数据类型——正如您所指出的,它具有出色的运行时性能特征,但它使用了一堆内存带你到那里。

真的,我认为@msw 的评论和@Udi 的回答是正确的——为了扩展你应该查看磁盘上或至少某种进程外的存储,可能 RDBMS 是最简单的东西开始吧。

但是,如果您确定需要保留在内存中并进行处理,我建议您使用排序列表来存储您的数据集。您可以在 O(log n) 时间内进行查找,并在恒定时间内进行插入和删除,并且您可以自己包装代码,以便使用看起来很像 defaultdict。像这样的东西可能会有所帮助(除了底部的测试之外没有调试):

import bisect

class mystore:
    def __init__(self, constructor):
        self.store = []
        self.constructor = constructor
        self.empty = constructor()

    def __getitem__(self, key):
        i, k = self.lookup(key)
        if k == key:
            return v
        # key not present, create a new item for this key.
        value = self.constructor()
        self.store.insert(i, (key, value))
        return value

    def __setitem__(self, key, value):
        i, k = self.lookup(key)
        if k == key:
            self.store[i] = (key, value)
        else:
            self.store.insert(i, (key, value))

    def lookup(self, key):
        i = bisect.bisect(self.store, (key, self.empty))
        if 0 <= i < len(self.store):
            return i, self.store[i][0]
        return i, None

if __name__ == '__main__':
    s = mystore(set)
    s['a'] = set(['1'])
    print(s.store)
    s['b']
    print(s.store)
    s['a'] = set(['2'])
    print(s.store)

【讨论】:

感谢您的回答,我最终使用了集合和交集,但这也是一个有效的解决方案 有趣,我认为sets 使用dict 作为底层数据存储,所以我认为您会在那里遇到相同类型的问题。我该去 RTFM 了 :)【参考方案2】:

也许可以试试 redis 的 set 数据类型:

Redis Set 是无序的字符串集合。 SADD 命令添加 集合的新元素。也可以做一些其他的 针对集合的操作,例如测试给定元素是否已经 存在...

从这里:http://redis.io/topics/data-types-intro

redis-py 支持这些命令。

【讨论】:

谢谢,我最终使用了集合,redis 集合是有用的东西。干杯!

以上是关于用于大型数据集的 Python defaultdict的主要内容,如果未能解决你的问题,请参考以下文章

计算大型数据集的python树高度

用于存储大型数据集的数据结构 [关闭]

R中用于大型复杂调查数据集的方法?

python中大型数据集的文本分类

用于大型数据集的 sklearn utils compute_class_weight 函数

在 python 中处理大型数据集的最佳方法