数据存储之道!CSV 、Parquet、HDFS

掌握了多种数据获取神兵,弹药库日渐充实。但新的问题来了:下载好的数据,你还在用 df.to_csv() 保存吗?如果数据量一大,你很快就会发现 CSV 格式的种种弊端。

为什么你的“武器库”需要抛弃 CSV?

CSV (逗号分隔值) 文件虽然直观、通用,但作为量化数据的存储格式,它至少有四大“原罪”:

  • 速度慢: 它是纯文本格式,读写时需要大量的解析和转换,I/O 效率极低。
  • 体积大: 文本存储通常比二进制存储占用更多空间,且默认不压缩。
  • 类型丢失: 当你再次读入 CSV 时,日期变成了字符串,数字可能也变成了字符串,你需要手动转换,非常麻烦。
  • 无元数据: 它无法存储数据的元信息(比如 schema 结构)。

在严肃的量化研究中,CSV 只应作为一种临时的数据交换格式,而不应作为核心的本地存储格式。

新武器一:Parquet (现代数据分析的首选)

Parquet 是一种列式存储格式,被广泛应用于大数据生态(如 Spark, Hadoop)。它的核心优势是:

  • 极速读取: 由于是按列存储,当你只需要读取几列数据时,它不必扫描整个文件,速度极快。
  • 高压缩比: 对同一列的数据进行压缩,效果通常远好于按行压缩。
  • 类型保持: 完美地保存了 DataFrame 的数据类型和 Schema。

使用 Pandas 读写 Parquet 非常简单,但需要先安装 pyarrow 引擎。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
import pandas as pd

# 假设 df 是我们之前获取的数据
df = pd.DataFrame({'A': [1, 2, 3], 'B': ['x', 'y', 'z']},
index=pd.to_datetime(['2023-01-01', '2023-01-02', '2023-01-03']))

# 保存到 Parquet 文件
df.to_parquet('my_data.parquet')

# 从 Parquet 文件读取
df_from_parquet = pd.read_parquet('my_data.parquet')

print("--- Data types from Parquet ---")
print(df_from_parquet.info()) # 注意看,数据类型和索引都完美保留了!

新武器二:HDF5 (文件中的“数据库”)

HDF5 (Hierarchical Data Format) 是另一种强大的二进制格式。你可以把它想象成一个“文件中的文件系统”。它最大的特点是层级结构,允许你在一个 HDF5 文件中,像在文件夹里一样,存储多个不同的数据集(DataFrame, Numpy Array等)。

使用 HDF5 需要安装 tables 引擎。

1
2
3
4
5
6
7
8
9
# 保存到 HDF5 文件
# 需要指定一个 'key',就像文件名一样
df.to_hdf('my_store.h5', key='daily_data', mode='w')

# 从 HDF5 文件中读取
df_from_hdf = pd.read_hdf('my_store.h5', key='daily_data')

print("\n--- Data from HDF5 ---")
print(df_from_hdf)

Parquet vs. HDF5,我该用哪个?

这是一个经典问题。对于大多数量化场景,Parquet 是更现代、更推荐的首选。

当你需要遵循“一个文件一个数据集”的最佳实践时,用 Parquet。它与现代数据工具(如 Dask, DuckDB)的集成更好。
当你确实有强需求,需要将多个相关但结构不同的数据集(比如一只股票的日线、分钟线、因子值)打包在同一个文件中时,HDF5 依然是很好的选择。