4. 数据探索与概览:DataFrame 基本信息查看、describe() 统计摘要、info() 数据类型检查

在量化策略回测中,原始数据(如日频 OHLCV、分钟级 Tick 数据)通常以 CSV、Parquet 或数据库形式存储。在进入清洗流程之前,必须对 DataFrame 进行系统性探索与概览。本章聚焦三个核心操作:info() 数据类型检查、describe() 统计摘要、以及基本信息查看(shape、columns、head/tail)。

核心原则:先概览后清洗。跳过数据探索直接清洗,容易遗漏缺失值模式、类型错误或异常分布,导致回测结果失真。

4.1 使用 info() 检查数据类型与内存

DataFrame.info() 是数据清洗的第一步,它一次性输出:列名、非空计数、数据类型(dtype)以及内存使用量。对于回测数据,常见问题包括:日期列被解析为 object 而非 datetime、成交量列被读为 float64 而非 int64、缺失值未正确识别。

import pandas as pd

# 加载示例日频数据
df = pd.read_csv('stock_600519_daily.csv')
df.info()

# 输出示例(非实际数据):
# <class 'pandas.core.frame.DataFrame'>
# RangeIndex: 2520 entries, 0 to 2519
# Data columns (total 7 columns):
#  #   Column     Non-Null Count  Dtype
# ---  ------     --------------  -----
#  0   date       2520 non-null   object
#  1   open       2520 non-null   float64
#  2   high       2520 non-null   float64
#  3   low        2520 non-null   float64
#  4   close      2518 non-null   float64
#  5   volume     2520 non-null   int64
#  6   amount     2520 non-null   float64
# dtypes: float64(5), int64(1), object(1)
# memory usage: 137.9+ KB
关键检查点:
  • 日期列:dtype 应为 datetime64[ns],若为 object 则需用 pd.to_datetime() 转换。
  • 数值列:OHLC 应为 float64,volume/amount 可为 int64 或 float64。若出现 object,说明存在非数字字符(如逗号、空格)。
  • 非空计数:若 Non-Null Count 小于总行数,表示存在缺失值,需后续处理。
  • 内存占用:大数据集(百万行以上)可考虑优化 dtype(如使用 int32、float32)以降低内存。

4.2 使用 describe() 获取统计摘要

DataFrame.describe() 对数值列自动计算:计数、均值、标准差、最小值、25%/50%/75% 分位数、最大值。对于回测数据,这些统计量能快速暴露异常值、分布偏态或数据范围错误。

# 对数值列生成统计摘要
df.describe()

# 输出示例(非实际数据):
#          open        high         low       close      volume       amount
# count  2520.00    2520.00     2520.00    2518.00    2520.00     2520.00
# mean    168.32     170.15      166.48     168.20   1.25e+07   2.10e+09
# std      12.45      12.78       12.10      12.33   3.20e+06   5.40e+08
# min     120.10     122.30      118.50     119.80   2.10e+06   3.50e+08
# 25%     158.20     160.10      156.80     158.00   9.80e+06   1.65e+09
# 50%     167.50     169.30      165.70     167.30   1.22e+07   2.05e+09
# 75%     177.80     179.60      176.00     177.50   1.50e+07   2.55e+09
# max     210.50     212.00      208.30     209.80   2.80e+07   4.80e+09
异常值警示:
  • 若 min 为负数(如开盘价 -1.0),说明数据存在错误或除权除息未复权。
  • 若 max 远超 75% 分位数(如 close 最大值为 9999),可能为数据录入错误或极端事件未过滤。
  • 若 count 不一致(如 close 只有 2518 行),需定位缺失行。
  • 若 std 为 0,说明该列所有值相同,可能是无效列。

4.3 基本信息查看:shape、columns、head/tail

在 info() 和 describe() 之前,快速查看 DataFrame 的轮廓有助于建立整体认知。

方法/属性 作用 回测场景示例
df.shape 返回 (行数, 列数) 确认数据是否覆盖完整回测周期(如 2520 行 ≈ 10 年交易日)
df.columns 返回列名列表 检查列名是否包含空格、大小写不一致(如 'Close' vs 'close')
df.head(n) 查看前 n 行 快速确认日期格式、数据起始点、列顺序
df.tail(n) 查看后 n 行 确认数据是否包含未来数据或最新交易日
df.sample(n) 随机抽取 n 行 检查数据分布是否均匀,避免头部/尾部偏差
# 快速轮廓检查
print('Shape:', df.shape)          # (2520, 7)
print('Columns:', df.columns.tolist())
print('Head:\n', df.head(3))
print('Tail:\n', df.tail(3))

4.4 数据探索流程总览

以下 SVG 图展示了从原始数据加载到清洗前的标准探索流程,包含三个核心步骤及其输出。

数据探索与概览流程 原始 DataFrame info() 类型检查 describe() 统计摘要 shape/head/tail 清洗决策依据 输出示例 缺失值位置 | 类型错误列 | 异常统计量 | 数据范围 | 内存占用

4.5 实战案例:快速诊断数据问题

假设我们加载了一份分钟级股指期货数据,通过三步探索发现以下问题:

  1. info() 发现:datetime 列为 object,volume 列为 float64 但应为 int64。
  2. describe() 发现:close 最小值 0.01,远低于正常价格,疑似数据错误;volume 标准差极大,可能存在异常大单。
  3. head/tail 发现:数据尾部包含未来日期(超出回测截止日),需截断。
清洗前必做清单:
  • ✅ 日期列转换为 datetime64
  • ✅ 数值列检查并修正 dtype
  • ✅ 标记缺失值位置(行号、列名)
  • ✅ 记录异常值阈值(如价格 < 0.1 或 > 均值+5σ)
  • ✅ 确认数据时间范围与回测周期一致