Python 直方图的numpy数组

Python 直方图的numpy数组,python,numpy,Python,Numpy,我目前正在使用一个2d numpy对象数组,其中填充了collections.counter对象 每个计数器基本上是一个直方图 键总是来自一组有限的整数,例如0到1500之间的整数 每个计数器中的项目数是可变的,大多数都很小,但有些计数器有每个键 对于较小的数据集,这一切都可以很好地满足我的需要,但是对于大约5亿个单元格的数据集,内存使用量大约为120Gb,这有点高 有趣的是,numpy.save将其写入4gb文件,这让我觉得我可以做得更好 关于如何减少内存使用的任何建议 我考虑了一个3d阵

我目前正在使用一个2d numpy对象数组,其中填充了collections.counter对象 每个计数器基本上是一个直方图

  • 键总是来自一组有限的整数,例如0到1500之间的整数
  • 每个计数器中的项目数是可变的,大多数都很小,但有些计数器有每个键
对于较小的数据集,这一切都可以很好地满足我的需要,但是对于大约5亿个单元格的数据集,内存使用量大约为120Gb,这有点高

有趣的是,numpy.save将其写入4gb文件,这让我觉得我可以做得更好

关于如何减少内存使用的任何建议

我考虑了一个3d阵列,但由于空计数的数量,它需要容纳更多的内存

我在构建数组时大量使用了counter.update,因此任何方法都需要一种快速/简洁的方式来获得类似的功能

创建数据后的访问不是一个大问题,只要每个单元格我都能得到每个键的值,就不需要字典索引

下面是一个非常简化的示例,它生成了一个小数据集,大致类似于我上面描述的。我的代码将进一步偏向于每个计数器更少的键和每个键更高的计数

def counterArray_init(v):
    return collections.Counter([v])

e = np.random.random_integers(0,1500,[10,10])
row_len, col_len = e.shape
counterArray = np.zeros([row_len,col_len], dtype= object)
vinit = np.vectorize(counterArray_init)
counterArray[:,:] = vinit(e)
for row in xrange(1,row_len):
    for col in xrange(0,col_len):
       counterArray[row,col].update(counterArray[row - 1,col])
return counterArray
谢谢

编辑:我已经意识到,在我较小的计数器中,使用的键在一个小范围内。上面的随机示例代码不是这种行为的好例子。
因此,我正在研究使用一个填充了不同长度的int数组的对象数组和一个单独的数组来存储每个int数组的最小键值。这似乎是一个奇怪的解决方案,但初始测试似乎只使用计数器方法使用的大约20%的内存。

如果有大量空计数,稀疏矩阵表示可能是一个很好的选择,其中内存使用与数组中非空元素的数量成比例。SciPy对你所看到的东西有很好的支持:

我肯定会使用3D数组,因为键是整数。特定物品的最大数量是多少?如果低于255,您还可以将数组的数据类型更改为8位。

一个快速测试显示,存储元组而不是
计数器
对象只会为您节省大约20%。(可能值得在您的用例中再次检查)。如果存储为纯整数数组的效率更低,那么就没有其他选择了

稀疏数组是一种很好的节省空间的方法,但它不提供与普通数组相同的boadcasting,它们通常只用于创建或存储数据,然后转换为普通数组进行计算。如果使用常规python循环遍历索引,那么稀疏数组可能是一个很好的解决方案


numpy.save
必须进行某种压缩。对内存中正在使用的数据不太可能有用的压缩。你在用还是?您目前如何管理120G数据-虚拟内存?

3D阵列将只是一个基本的numpy阵列,dtype=int,对吗?没有计数器对象?没错,只是一个整数的3d numpy数组。好主意,但可以在100k+范围内计数。有了这个限制,一个普通的3d阵列将无法在合理的内存限制下工作。我将查看稀疏矩阵,尽管如果我正确读取,它们将被限制为2d,因此我需要展平一维。另外,你有没有任何关于如何使用对象数组中的元组列表节省20%的counter.updatewas的等效方法的建议?我不希望像numpy.save那样紧凑。我可以访问一台具有500G ram的机器,但我希望该解决方案能够扩展到更大的阵列或移动到更小的机器。如果我没有在不同的数据结构中得到显著的改进,我将在pytables中查找。@Art我所做的只是将python元组的大小与元素数相同的计数器进行比较。我使用了这个方法:我认为将元组转换为集合进行处理,然后再转换回元组进行存储可能很容易。从而在更复杂的对象中节省所有额外开销的存储。当然,您的里程数会随着每个对象存储的元素数量的不同而变化。您不会找到一个更高效的数据结构。但是,如果密集的3d阵列表示没有那么大,那么将其存储为压缩的hdf5阵列可能是一个不错的选择。在更基本的层面上;我怀疑这个庞大的阵列本身就是一个目标;我想它会在以后的阶段减少;您能否不融合这些程序阶段,而只以惰性方式计算所需数据结构的一部分?我对numpy感到非常惊讶。顺便说一句,保存性能。这是否真的正确加载,或者这是一个带有计数器的错误?