4. 数据获取与加载

在机器学习Alpha项目的端到端流程中,数据获取与加载是决定后续特征工程、模型训练与回测质量的第一道关口。很多初学者把注意力集中在模型调参上,却忽略了数据源接入方式、编码格式、字段类型推断等细节,导致后续出现“看似模型问题、实为数据问题”的隐性故障。本节将围绕CSV、Excel、数据库、API四类常见来源,讲解如何用Pandas完成加载、初步查看与质量判断。

一、核心原理:数据加载的本质是“解析+类型推断+内存映射”

无论数据来自哪种介质,Pandas加载过程都可以抽象为三个动作:首先按分隔符或协议解析原始字节流,其次根据样本推断每列的dtype(整数、浮点、布尔、日期、类别或对象),最后将结果写入DataFrame的块管理器。理解这一点,就能解释为什么同一份CSV在不同机器上读出的类型可能不同,也能解释为什么大文件读取时内存会突然飙升。

关键认知:read_csv并不是“打开文件”那么简单,它同时完成了编码解码、缺失值识别、类型推断和索引构建。任何一步参数设置不当,都会在后续df.info()或df.describe()中暴露出来。

二、方法流程:四类数据源的加载与初步查看

下面按数据源类型给出标准操作路径,并统一使用head()、info()、describe()、isna().sum()四件套进行初步体检。

1. CSV文件:最常用也最容易踩坑

import pandas as pd

df = pd.read_csv(
    "alpha_features.csv",
    encoding="utf-8",
    sep=",",
    parse_dates=["trade_date"],
    dtype={"stock_code": "string", "industry": "category"},
    na_values=["", "NULL", "None", "-"]
)

print(df.head())
print(df.info())
print(df.describe(include="all"))
print(df.isna().sum().sort_values(ascending=False))

重点参数包括:encoding解决中文乱码,parse_dates避免日期被读成字符串,dtype防止股票代码前导零丢失,na_values统一缺失值表示。若文件超过内存,可使用chunksize分块读取。

2. Excel文件:注意工作表与合并单元格

df_excel = pd.read_excel(
    "alpha_factor.xlsx",
    sheet_name="Sheet1",
    header=0,
    usecols="A:H",
    engine="openpyxl"
)
print(df_excel.shape)
print(df_excel.columns.tolist())

Excel常见问题是多行表头、合并单元格和隐藏列。建议先用sheet_name=None读取全部工作表,确认目标表后再指定header与usecols。

3. 数据库:用SQL把过滤下推到源头

from sqlalchemy import create_engine

engine = create_engine("mysql+pymysql://user:pwd@host:3306/alpha")
sql = "SELECT trade_date, stock_code, close, volume FROM daily_bar WHERE trade_date >= '2024-01-01'"
df_db = pd.read_sql(sql, engine)
print(df_db.dtypes)

数据库加载的核心原则是“能下推就下推”:过滤、聚合、排序尽量写在SQL里,避免把全表拉进内存再筛选。同时注意时区、数值精度和空值在数据库与Pandas之间的语义差异。

4. API接口:处理分页、限流与嵌套JSON

import requests, pandas as pd

resp = requests.get("https://api.example.com/alpha/quotes", params={"date": "2024-06-01"}, timeout=10)
data = resp.json()["data"]
df_api = pd.json_normalize(data)
print(df_api.head())

API数据常为嵌套JSON,使用json_normalize可展开层级字段。务必处理分页游标、请求限流和失败重试,否则会得到不完整数据集。

三、案例场景:Alpha因子数据接入的初步体检

假设我们从上述四个来源分别获取了日频行情、财务指标、行业分类和实时快照。加载后应统一执行以下清单,判断数据是否可用于后续建模。

检查项 Pandas操作 合格标准 常见异常
行列规模 df.shape 与预期交易日×股票数一致 行数偏少,分页未取全
字段类型 df.dtypes 日期为datetime,代码为string 数值被读成object
缺失分布 df.isna().sum() 关键字段缺失率低于阈值 停牌日被误判为缺失
重复记录 df.duplicated().sum() 主键组合无重复 多源合并产生重复行
数值范围 df.describe() 价格、成交量在合理区间 单位不一致或异常极值
四类数据源 → Pandas加载 → 初步体检 CSV文件 read_csv / 编码 / 分块 Excel文件 read_excel / 工作表 数据库 read_sql / 下推过滤 API接口 requests / json_normalize Pandas DataFrame 解析 · 类型推断 · 内存映射 索引 · 缺失值识别 统一字段与时间轴 head / info 结构与类型确认 describe 分布与极值检查 isna / duplicated 缺失与重复排查 dtypes / shape 规模与类型验收

四、误区与复盘:加载阶段最容易犯的五个错误

  • 忽略编码与分隔符:中文CSV用默认utf-8读取可能报错,应尝试gbk或utf-8-sig;分隔符可能是分号或制表符。
  • 让Pandas自由推断类型:股票代码“000001”会被读成整数1,日期会被读成字符串。应显式指定dtype和parse_dates。
  • 把全表拉进内存:数据库查询缺少WHERE条件、API未分页,都会导致内存溢出。应优先在源头过滤。
  • 只看head就下结论:前五行正常不代表全量正常。必须结合info()、describe()和缺失统计。
  • 多源合并前未对齐主键:不同来源的股票代码、日期格式、时区不一致,直接merge会产生大量空值或重复行。
建议在项目初期就封装一个load_and_check(path_or_sql)函数,把编码、类型、缺失值、重复值检查固化为标准动作。这样每次接入新数据源时,都能在几分钟内完成初步体检,而不是等到模型效果异常时才回头排查数据。
特别注意:read_csv的low_memory默认行为可能导致混合类型列被分块推断,出现类型不一致。对于字段较多的宽表,建议显式设置low_memory=False或指定dtype,避免后续出现难以定位的类型错误。

完成本节的数据获取与加载后,你应当能够针对任意一个Alpha项目数据源,选择合适的读取方式,设置关键参数,并用四件套快速判断数据是否具备进入特征工程阶段的基本条件。数据加载不是简单的“读进来”,而是端到端项目中第一个需要严谨对待的质量控制点。