使用Python将大量数字写入HDF5文件

时间:2016-10-16 14:30:16

标签: python numpy hdf5 numpy-broadcasting

我目前有一个包含一百万行的数据集,每行约10000列(可变长度)。

现在我想将这些数据写入HDF5文件,以便稍后使用。 我让这个工作,但它非常慢。即使1000个值也需要几分钟才能存储在HDF5文件中。

我一直在寻找各地,包括SO和H5Py文档,但我找不到任何描述我的用例的内容,但我知道可以做到。

下面我制作了一个演示源代码,描述了我现在正在做的事情:

import h5py
import numpy as np

# I am using just random values here
# I know I can use h5py broadcasts and I have seen it being used before.
# But the issue I have is that I need to save around a million rows with each 10000 values
# so I can't keep the entire array in memory.
random_ints = np.random.random(size = (5000,10000))

# See http://stackoverflow.com/a/36902906/3991199 for "libver='latest'"
with h5py.File('my.data.hdf5', "w", libver='latest') as f:
    X = f.create_dataset("X", (5000,10000))
    for i1 in range(0, 5000):
        for i2 in range(0, 10000):
            X[i1,i2] = random_ints[i1,i2]

        if i1 != 0 and i1 % 1000 == 0:
            print "Done %d values..." % i1

这些数据来自数据库,它不是预先生成的np数组,如源代码所示。

如果您运行此代码,您可以看到它在打印出“完成1000个值”之前需要很长时间。

我的笔记本电脑配备8GB内存,Ubuntu 16.04 LTS和英特尔酷睿M(其功能与Core i5类似)和SSD,必须足够快,速度要快一些。

我在这里阅读了有关广播的内容:http://docs.h5py.org/en/latest/high/dataset.html

当我像这样使用它时:

for i1 in range(0, 5000):
        X[i1,:] = random_ints[i1]

它的速度已经快了很多(完成几秒钟)。但我不知道如何使用可变长度数据集(列是可变长度)。如何获得一些关于如何做到这一点的见解会很高兴,因为我认为我现在对HDF5的概念并不是很了解:)非常感谢!

1 个答案:

答案 0 :(得分:1)

关注http://docs.h5py.org/en/latest/special.html

并使用打开的h5文件f,我试过了:

dt = h5py.special_dtype(vlen=np.dtype('int32'))
vset=f.create_dataset('vset', (100,), dtype=dt)

逐个设置元素:

vset[0]=np.random.randint(0,100,1000)    # set just one element
for i in range(100):    # set all arrays of varying length
    vset[i]=np.random.randint(0,100,i)
vset[:]      # view the dataset

或制作一个对象数组:

D=np.empty((100,),dtype=object)
for i in range(100):   # setting that in same way
    D[i]=np.random.randint(0,100,i)

vset[:]=D    # write it to the file

vset[:]=D[::-1]   # or write it in reverse order

最后一次写作的一部分:

In [587]: vset[-10:]
Out[587]: 
array([array([52, 52, 46, 80,  5, 89,  6, 63, 21]),
       array([38, 95, 51, 35, 66, 44, 29, 26]),
       array([51, 96,  3, 64, 55, 31, 18]),
       array([85, 96, 30, 82, 33, 45]), array([28, 37, 61, 57, 88]),
       array([76, 65,  5, 29]), array([78, 29, 72]), array([77, 32]),
       array([5]), array([], dtype=int32)], dtype=object)

我可以用以下内容查看元素的部分:

In [593]: vset[3][:10]
Out[593]: array([86, 26,  2, 79, 90, 67, 66,  5, 63, 68])

但我无法将其视为二维数组:vset[3,:10]。这是一个数组阵列。