我有一个这样的课程:
class C:
def __init__(self, id, user_id, photo):
self.id = id
self.user_id = user_id
self.photo = photo
我需要创建数百万个这些对象。 id是一个整数以及user_id,但是photo是一个大小为64的bool数组。我的老板要我将所有这些存储在hdf5文件中。我还需要能够根据其user_id属性进行查询,以获得具有相同user_id的所有照片。首先,我如何存储它们?甚至可以吗?其次,一旦我存储(如果我可以)他们如何查询它们?谢谢。
答案 0 :(得分:3)
虽然您可以将整个数据结构存储在单个HDF5表中,但将所描述的类存储为三个单独的变量(两个一维整数数组和一个用于存储“照片”属性的数据结构)可能要容易得多。 / p>
如果您关心文件大小和速度而不关心文件的人类可读性,您可以将64个bool值建模为UINT8的8个1D阵列或UINT8(或CHAR)的2个阵列N x 8 。然后,您可以实现一个简单的接口,将您的bool值打包到UINT8的位中并返回(例如,How to convert a boolean array to an int array)
据我们所知,HDF5中没有内置搜索功能,但您可以读取包含user_ids
的变量,然后只需使用Python查找与user_id
匹配的所有元素的索引
获得索引后,您可以读入其他变量的相关切片。 HDF5原生支持高效切片,但它适用于范围,因此您可能想要考虑如何在连续块中存储具有相同user_id
的记录,请参阅此处的讨论
h5py: Correct way to slice array datasets
您可能还想查看pytables - 一个python interace,它构建在hdf5上,用于将数据存储在类似表格的结构中。
import numpy as np
import h5py
class C:
def __init__(self, id, user_id, photo):
self.id = id
self.user_id = user_id
self.photo = photo
def write_records(records, file_out):
f = h5py.File(file_out, "w")
dset_id = f.create_dataset("id", (1000000,), dtype='i')
dset_user_id = f.create_dataset("user_id", (1000000,), dtype='i')
dset_photo = f.create_dataset("photo", (1000000,8), dtype='u8')
dset_id[0:len(records)] = [r.id for r in records]
dset_user_id[0:len(records)] = [r.user_id for r in records]
dset_photo[0:len(records)] = [np.packbits(np.array(r.photo, dtype='bool').astype(int)) for r in records]
f.close()
def read_records_by_id(file_in, record_id):
f = h5py.File(file_in, "r")
dset_id = f["id"]
data = dset_id[0:2]
res = []
for idx in np.where(data == record_id)[0]:
record = C(f["id"][idx:idx+1][0], f["user_id"][idx:idx+1][0], np.unpackbits( np.array(f["photo"][idx:idx+1][0], dtype='uint8') ).astype(bool))
res.append(record)
return res
m = [ True, False, True, True, False, True, True, True]
m = m+m+m+m+m+m+m+m
records = [C(1, 3, m), C(34, 53, m)]
# Write records to file
write_records(records, "mytestfile.h5")
# Read record from file
res = read_records_by_id("mytestfile.h5", 34)
print res[0].id
print res[0].user_id
print res[0].photo