如何提高HDF5读取数据的性能?



我需要的是尽快得到unique date的值。

我使用代码df = store.df.date.drop_duplicates()检索。这行代码采用6 seconds。但是,如果我使用mysql并将相同的数据保存到mysql,我将mysql用于indexing之后的日期列,使用sql:select distinct date from table,只需要80ms来检索唯一的date值,这是60 times比HDF5快。

是否有办法使read_unique_date读取HDF5的速度比MySQLuses indexes快?

我的代码如下:
import pandas as pd
import numpy as np
from itertools import product
from time import time

def generate_data():
np.random.seed(202108)
# date = pd.date_range(start="19900101", end="20210723", freq="D")
#The above is my original code, you can use the following code to speed up the operation.
date = pd.date_range(start="20210101", end="20210723", freq="D")
date = pd.DataFrame(date, columns=["date"])
# code = pd.DataFrame(range(5000), columns=["code"])
#The above is my original code, you can use the following code to speed up the operation.
code = pd.DataFrame(range(50), columns=["code"])
# generate product of the two columns:
df = pd.DataFrame(product(date["date"], code["code"]), columns=["date", "code"])
df['data'] = np.random.random(len(df))
return df

def save_data(filename, df):
store = pd.HDFStore(filename)
store['df'] = df
store.close()
return

def read_unique_date(file_name):
store = pd.HDFStore(file_name)
start = time()
df = store.df.date.drop_duplicates()
store.close()
stop = time()
print(stop - start)
return df

def main():
path = 'd:\'
file = 'large data.h5'
file_name = path + file
df = generate_data()
save_data(file_name, df)
df1 = read_unique_date(file_name)
print(df1)
return df1

if __name__ == '__main__':
main()

结果是:

0.015624761581420898
0       2021-01-01
50      2021-01-02
100     2021-01-03
150     2021-01-04
200     2021-01-05
...    
9950    2021-07-19
10000   2021-07-20
10050   2021-07-21
10100   2021-07-22
10150   2021-07-23
Name: date, Length: 204, dtype: datetime64[ns]
%timeit df1 = read_unique_date(file_name)
16.9 ms ± 200 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

原始代码的结果:

%timeit df1 = read_unique_date(file_name)
4.89 s ± 119 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

简短的回答是HDF5除了数据集(数据集名称)的键和连续数组索引之外根本没有索引。因此,直接从文件中执行的次线性查找操作只能是检索数据集中的第n个值。要直接从文件中找到唯一的值,HDF5必须读取整个文件。你可能会用HDF5组和引用制作一些混乱但功能强大的东西,但你只是自己实现索引,我不建议走这条路。

另一方面,Pandas使用哈希表、树和二叉查找来加速各种查找操作。您可以将数据加载到数据框架中以进行查询。但一般情况下,您希望在某个时候转移到合适的数据库。熊猫和HDF5只能带你到此为止。

pandas在这里有一个名为read_hdf的方法。您可以简单地读取存储的.h5,并写入:

read_df = pd.read_hdf('./large data.h5')

,你可以访问read_df作为pandas数据帧

现在,如果你问我,存储文件并再次读取它以用于周期性循环,这不是一个好主意。我会保持数据帧的形式,只在必要时写它(即我需要内存中的空间,或者我需要更新数据库与一些共享访问)。我认为应该考虑对写和读进行策略化,以优化代码运行。

顺便说一句,你的代码使我的调试崩溃了:

df = pd.DataFrame(product(date["date"], code["code"]), columns=["date", "code"])

你可能需要再看一遍。

您的代码是按原样运行的,所以如果没有您想要的输出示例,就很难告诉您想要得到什么。这段代码生成的近1.8 GB的数据与您的问题无关,除非我错过了一些东西,这确实是一个与性能相关的问题。如果以下方法不能解决您的问题,我建议您大幅减少生成的数据,并提供所需输出的示例,这样人们就可以帮助您,而不必假设您想要得到什么。

我猜你们想要的是什么,我认为问题在于你们如何消除重复。您正在删除数据帧设置df中包含的日期序列中的重复项,df等于这个缩减后的序列。相反,我认为您需要的是使用df. drop_duplates()从数据框中删除重复项,并指定日期列作为子集。

示例:df.drop_duplicates(subset="date").

这能解决你的问题吗?

最新更新