大阵列的Numpy直方图

gar*_*ois 15 python numpy histogram scipy

我有一堆csv数据集,每个大小约10Gb.我想从他们的列生成直方图.但似乎在numpy中执行此操作的唯一方法是首先将整个列加载到numpy数组中,然后调用numpy.histogram该数组.这会消耗不必要的内存量.

numpy支持在线分类吗?我希望能够在读取它们的同时逐行迭代我的csv.这种方式在任何时候最多一行都在内存中.

不难自我动手,但想知道是否有人已经发明了这个轮子.

mtr*_*trw 12

正如你所说,推出自己的并不难.您需要自己设置垃圾箱,并在迭代文件时重复使用它们.以下应该是一个不错的起点:

import numpy as np
datamin = -5
datamax = 5
numbins = 20
mybins = np.linspace(datamin, datamax, numbins)
myhist = np.zeros(numbins-1, dtype='int32')
for i in range(100):
    d = np.random.randn(1000,1)
    htemp, jnk = np.histogram(d, mybins)
    myhist += htemp
Run Code Online (Sandbox Code Playgroud)

我猜测性能会对这么大的文件造成问题,并且在每一行调用直方图的开销可能太慢了. @doug建议使用生成器似乎是解决这个问题的好方法.


dou*_*oug 6

这是一种直接存储您的值的方法:

import numpy as NP

column_of_values = NP.random.randint(10, 99, 10)

# set the bin values:
bins = NP.array([0.0, 20.0, 50.0, 75.0])

binned_values = NP.digitize(column_of_values, bins)
Run Code Online (Sandbox Code Playgroud)

'binned_values'是一个索引数组,包含column_of_values中每个值所属的bin的索引.

'bincount'会给你(显然)bin计数:

NP.bincount(binned_values)
Run Code Online (Sandbox Code Playgroud)

给定数据集的大小,使用Numpy的'loadtxt'构建生成器可能很有用:

data_array = NP.loadtxt(data_file.txt, delimiter=",")
def fnx() :
  for i in range(0, data_array.shape[1]) :
    yield dx[:,i]
Run Code Online (Sandbox Code Playgroud)

  • 但是不会加载文件首先将整个文件加载到内存中吗?这正是我想要避免的问题. (3认同)

Dan*_*n H 5

用 Fenwick 树分箱 (非常大的数据集;需要百分位边界)

我发布了同一问题的第二个答案,因为这种方法非常不同,并且解决了不同的问题。

如果您有一个非常大的数据集(数十亿个样本),并且您不知道您的 bin 边界应该在哪里,该怎么办?例如,也许您想将事物分成四分位数或十分位数。

对于小数据集,答案很简单:将数据加载到数组中,然后排序,然后通过跳转到数组中该百分比的索引读取任何给定百分位数的值。

对于容纳数组的内存大小不切实际的大型数据集(更不用说排序的时间了)......然后考虑使用 Fenwick 树,又名“二进制索引树”。

我认为这些仅适用于正整数数据,因此您至少需要对数据集有足够的了解才能在 Fenwick 树中制表之前移动(并可能缩放)数据。

我已经使用它在合理的时间和非常舒适的内存限制内找到了 1000 亿个样本数据集的中位数。(根据我的其他答案,考虑使用生成器打开和读取文件;这仍然很有用。)

有关 Fenwick 树的更多信息: