我尝试使用pandas库读取64 GB的HDF文件(使用blosc压缩)。 Dataframe包含3列和11410996915行。我试图通过方法pandas.read_hdf和参数where选择具体的行。问题是有时我需要获得数千行,所以在我的where参数中我放了这样的东西:
simMat = pd.read_hdf('global.h5','matrix', columns=['similarity'], where='index in {}'.format(listIdx))
其中listIdx是表示我想要返回的索引的integeres列表。当此列表包含超过31个元素时,我收到内存错误。我开始查看pandas库的代码并发现在文件pytables.py中,在BinOp类中有一个名为_max_selectors的变量,它已赋值为31.此变量在此段代码之后使用:
# if too many values to create the expression, use a filter instead
if self.op in ['==', '!='] and len(values) > self._max_selectors:
filter_op = self.generate_filter_op()
self.filter = (
self.lhs,
filter_op,
pd.Index([v.value for v in values]))
return self
使用过滤器会导致库尝试加载整个数据帧,这会导致MemoryError。我试图使用值为10的chunksize参数,但它也不起作用。您是否知道使用如此大量的索引查询HDF文件的更好方法?
答案 0 :(得分:1)
您可以使用以下技术:
pd.read_hdf(filename, 'key', where='index = vals')
其中vals
是pd.Series
或Python list
变量
您还可以使用属于其他DF的列进行过滤:
In [201]: another_df = pd.DataFrame(np.random.randint(0, 100, size=(100, 3)), columns=list('abc'))
In [202]: pd.read_hdf(fn, 'test', where='a = another_df["a"]').shape
Out[202]: (573, 3)
或其他DF指数:
In [203]: pd.read_hdf(fn, 'test', where='index = another_df.index').shape
Out[203]: (100, 3)
演示:
设置
fn = r'D:\temp\.data\hdf\test.h5'
store = pd.HDFStore(fn)
df = pd.DataFrame(np.random.randint(0, 10**4, size=(10**5, 3)), columns=list('abc'))
store.append('test', df, data_columns=True, complib='blosc', complevel=5)
store.close()
测试
vals = pd.Series(np.random.randint(0, 100, 500))
In [196]: pd.read_hdf(fn, 'test', where='index = vals').shape
Out[196]: (98, 3)
与Python列表相同:
idx_list = vals.tolist()
In [197]: pd.read_hdf(fn, 'test', where='index = idx_list').shape
Out[197]: (98, 3)