用于大型数据集的 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
的有用消息。我知道defaultdict
s 内存很重,但是是否有使用defaultdict
s 进行存储的优化方法,或者我是否必须查看其他数据结构,例如 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)
【讨论】:
感谢您的回答,我最终使用了集合和交集,但这也是一个有效的解决方案 有趣,我认为set
s 使用dict
作为底层数据存储,所以我认为您会在那里遇到相同类型的问题。我该去 RTFM 了 :)【参考方案2】:
也许可以试试 redis 的 set 数据类型:
Redis Set 是无序的字符串集合。 SADD 命令添加 集合的新元素。也可以做一些其他的 针对集合的操作,例如测试给定元素是否已经 存在...
从这里:http://redis.io/topics/data-types-intro
redis-py 支持这些命令。
【讨论】:
谢谢,我最终使用了集合,redis 集合是有用的东西。干杯!以上是关于用于大型数据集的 Python defaultdict的主要内容,如果未能解决你的问题,请参考以下文章