我有一堆csv数据集,每个大小约为10GB。我想从它们的列生成直方图。但似乎在numpy中唯一的方法是先将整个列加载到numpy数组中,然后对该数组调用numpy.histogram
。这会消耗大量的内存。
numpy是否支持在线分箱?我希望有一种迭代我的csv文件,并在读取值时进行分箱的方法。这样,最多只有一行在内存中。
自己编写不难,但想知道是否已经有人发明了这个轮子。
如你所说,自己编写并不难。你需要自己设置垃圾箱,并在文件迭代过程中重复使用它们。以下应该是一个不错的起点:
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
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)
'binned_values'是一个索引数组,包含了每个在column_of_values列中的值所属的箱子的索引。
'bincount'会给出(显然)箱子计数:NP.bincount(binned_values)
考虑到你的数据集的大小,使用Numpy的“loadtxt”构建生成器可能是有用的:
data_array = NP.loadtxt(data_file.txt, delimiter=",")
def fnx() :
for i in range(0, data_array.shape[1]) :
yield dx[:,i]
使用生成器进行分箱(大型数据集;定宽箱子;浮点数数据)
如果您事先知道所需箱子的宽度 - 即使有成百上千个桶 - 那么我认为自己编写解决方案会很快(无论是编写还是运行)。以下是一些使用Python的代码,假设您有一个迭代器,可以从文件中获取下一个值:
from math import floor
binwidth = 20
counts = dict()
filename = "mydata.csv"
for val in next_value_from_file(filename):
binname = int(floor(val/binwidth)*binwidth)
if binname not in counts:
counts[binname] = 0
counts[binname] += 1
print counts
这些值可以是浮点数,但前提是你使用整型的binwidth;如果要使用某个浮点数值作为binwidth,则可能需要进行一些微调。
至于next_value_from_file()
,如前所述,你可能需要编写自定义生成器或对象,并使用iter()方法以实现高效读取。该生成器的伪代码如下:
def next_value_from_file(filename):
f = open(filename)
for line in f:
# parse out from the line the value or values you need
val = parse_the_value_from_the_line(line)
yield val
parse_the_value_from_the_line()
要么返回一个列表,要么本身就是一个生成器,并使用以下伪代码:def next_value_from_file(filename):
f = open(filename)
for line in f:
for val in parse_the_values_from_the_line(line):
yield val
myhist += htemp
(我猜这样会更快,因为它直接在原地更新直方图)。 - Eric O. Lebigot