## 前言
最近在写的策略框架需要对数据进行频繁读取,传统的sqlite肯定不考虑,因为数据量比较大,读取速度太慢,所以考虑使用其他格式存储数据。常见的df存储格式有csv,hdf5,feather,Parquet,本文将对这几种格式进行测试,看看哪一种格式最适合我。
## 测试代码
参考了以下代码:https://github.com/stefan-jansen/machine-learning-for-trading/blob/master/02_market_and_fundamental_data/05_storage_benchmark/storage_benchmark.ipynb
“`python
from pathlib import Path
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
import random
import string
results = {}
def generate_test_data(nrows=1000, numerical_cols=200, text_cols=0, text_length=10):
s = “”.join([random.choice(string.ascii_letters)
for _ in range(text_length)])
data = pd.concat([pd.DataFrame(np.random.random(size=(nrows, numerical_cols))),
pd.DataFrame(np.full(shape=(nrows, text_cols), fill_value=s))],
axis=1, ignore_index=True)
data.columns = [str(i) for i in data.columns]
return data
data_type = ‘Numeric’
df = generate_test_data(numerical_cols=200, text_cols=10) # 数据生成
df.info()
parquet_file = Path(‘test.parquet’) # 以parquet为例
df.to_parquet(parquet_file)
size = parquet_file.stat().st_size
%%timeit -o
df = pd.read_parquet(parquet_file) # 读取
read = _
parquet_file.unlink()
%%timeit -o
df.to_parquet(parquet_file) # 写入
parquet_file.unlink()
write = _
results[‘Parquet’] = {‘read’: np.mean(read.all_runs), ‘write’: np.mean(write.all_runs), ‘size’: size}
results[‘Parquet’] # 测试结果保存
“`
pandas读取写入这些格式的代码:
“`python
df = pd.read_parquet(parquet_file) # parquet读取
df.to_parquet(parquet_file) # parquet写入
with pd.HDFStore(test_store) as store:
store.get(key) # HDF Fixed、HDF Table、HDF Select读取
with pd.HDFStore(test_store) as store:
store.put(key, df) # HDF Fixed写入
store.append(‘file’, df, format=’t’) # HDF Table写入
store.append(‘file’, df, format=’t’, data_columns=[‘company’, ‘form’]) # HDF Select写入
pd.read_csv(test_csv) # csv读取
df.to_csv(test_csv) # csv写入
pd.read_feather(test_feather) # feather读取
df.to_feather(test_feather) # feather写入
“`
## 测试结果
共测试了三个不同大小的数据集,其中表头为数据集占用内存大小,因为电脑性能原因,我没办法测试更大的数据了(实际上HDF Table和Select就因为内存爆了所以没有测试结果)。测试结果如下。
| | | 1.6+MB | 152.6+ MB | 1.5+ GB |
| – | – | – | – | – |
| **Read** | Parquet | 22.5 ms | 697 ms | 5.14 s |
| | HDF Fixed | 9.9 ms | 3.21 s | 81 s |
| | HDF Table | 16.1 ms | 7.41 s | |
| | HDF Select | 15.6 ms | 7.36 s | |
| | csv | 47.5 ms | 3.92 s | 41.9 s |
| | feather | 3.79 ms | 390 ms | 4.14 s |
| **Write** | Parquet | 34.4 ms | 3.71 s | 33.7 s |
| | HDF Fixed | 11.9 ms | 3.23 s | 51 s |
| | HDF Table | 17.9 ms | 8.49 s | |
| | HDF Select | 17.8 ms | 8.49 s | |
| | csv | 301 ms | 18.3 s | 191 s |
| | feather | 13 ms | 1.98 s | 17.2 s |
| **Size** | Parquet | 1.88MB | 94.12MB | 966.96MB |
| | HDF Fixed | 2.67MB | 201.41MB | 2004.86MB |
| | HDF Table | 1.76MB | 172MB | |
| | HDF Select | 1.76MB | 172MB | |
| | csv | 3.79MB | 288.74MB | 2887.42MB |
| | feather | 1.67MB | 209.95MB | 2098.23MB |
可以看到,三种不同大小的数据集中,feather读写速度都一枝独秀,大小占用中规中矩。Parquet在小数据集上表现较差,但随着数据量的增加,其读写速度相比与其他格式就有了很大优势,在大数据集上,Parquet的读取速度甚至能和feather一较高下,可以想象数据量突破2G后,Parquet的读取速度可能就是最快的了。但是在写方面,Parquet一直没有表现出超越feather的势头。Parquet另外一个优势就是压缩率高,占用空间相比于其他格式一直是比较小的。hdf比较尴尬,在小数据集上打不过feather,在大数据集上的读取速度甚至比不上csv。至于csv就不用说了,各方面拉跨。
值得注意的是,feather虽然快,但是它不支持dataframe的index,也就是说你传入带index的df它会报错……
看了测试结果,相信你心中已经有了各个格式的应用场景。尴尬的是,我的单个数据集刚好只有40M,这个场景下用Parquet感觉没啥必要……Read More