numpy
结构化数组是 Python 的替代品吗dict
?
我想节省内存,但我无法承受性能下降太多。
就我而言,键是str
,值是int
。
如果它们实际上是替代品,你能给出一个快速的转换线吗?
我也不介意您是否可以提出不同的选择。
我需要节省内存,因为某些字典的内存大于 50Gb,我需要一次打开多个字典,并且“只有”192 GB RAM 可用。
numpy
结构化数组是 Python 的替代品吗dict
?
我想节省内存,但我无法承受性能下降太多。
就我而言,键是str
,值是int
。
如果它们实际上是替代品,你能给出一个快速的转换线吗?
我也不介意您是否可以提出不同的选择。
我需要节省内存,因为某些字典的内存大于 50Gb,我需要一次打开多个字典,并且“只有”192 GB RAM 可用。
numpy 数组使用连续的内存块,并且只能存储一种类型的对象,如 int、float、string 或其他对象。每个项目在内存中分配固定字节。
Numpy 还提供了一组函数用于操作,如遍历数组、算术运算、对使用 c 实现的那些存储项的一些字符串操作。由于这些操作没有 python 的开销,因此它们在内存和处理能力方面通常更有效
当您需要键值对时,您也可以将其存储在类似于 c-struct 的 numpy 数组中,但它不会具有 dict 之类的功能,例如查找项目、检查键是否存在过滤等。您必须使用数组功能自己做这些
对您来说更好的选择可能是 pandas 系列,它还使用 numpy 数组来存储其数据,以便在其之上为您提供许多功能
也许有点晚了,但如果其他人有同样的问题,我做了一个简单的基准测试:
In [1]: import random
In [2]: import string
In [3]: import pandas as pd
In [4]: import sys
In [5]: size = 10**6
In [6]: d = {''.join(random.choices(string.ascii_letters + string.digits, k=32)): random.randrange(size) for _ in range(size)}
In [7]: s = pd.Series(d)
In [8]: a = s.values.view(list(zip(s.index, ['i8'] * size)))
In [9]: key = s.index[random.randrange(size)]
In [10]: %timeit d[key]
61.5 ns ± 1.46 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)
In [11]: %timeit s[key]
3.54 µs ± 158 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
In [12]: %timeit a[key]
154 ns ± 1.63 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)
In [13]: sys.getsizeof(d)
Out[13]: 41943136
In [14]: sys.getsizeof(s)
Out[14]: 130816632
似乎np.ndarray
比dict
(这是可以接受的)慢了大约 2-3 倍,而性能pd.Series
比其他两个差得多。至于空间效率,dict
也跑赢大盘pd.Series
。我没有找到一种方法来获取 numpy 结构化数组的内存使用情况(尝试使用sys.getsizeof
and ndarray.nbytes
,但似乎两者都缺少字段的大小)。
您可以使用对象的内存大小sys
import sys
import numpy as np
x = np.array([('Rex', 9, 81.0), ('Fido', 3, 27.0)],
dtype=[('name', 'U10'), ('age', 'i4'), ('weight', 'f4')])
print(sys.getsizeof(x))
y = {
1 : {
'name': 'Rex',
'age' : 9,
'weight' : 81.0
},
2 : {
'name': 'Fido',
'age' : 3,
'weight' : 27.0
}
}
print(sys.getsizeof(y))
这些是结果。我相信 numpy 结构化数组的内存效率相对较高。