A4. 数据获取与清洗
数据清洗往往占据一个分析项目 60–70% 的时间。本章围绕「读取 → 探索 → 清洗 → 变换」的标准流程,提供配套的提示词框和验证性追问模板。
本章的一个重要原则: 每完成一步清洗操作,都要用追问模板让 AI 帮你验证结果是否合理,不要等到最后才发现数据在某个中间步骤已经出了问题。
A4.1 生成模拟数据
在正式分析前,先用模拟数据测试代码是个好习惯——不需要等到真实数据准备好,也不担心测试过程污染原始数据。
提示词:生成金融面板模拟数据
这组提示词用于生成结构上接近真实 A 股数据的模拟数据框,适合在没有 Wind 权限时测试代码逻辑。
请用 Python 的 pandas 和 numpy 生成一份模拟金融面板数据集,
设置随机种子 np.random.seed(42) 确保可复现,要求如下:
数据结构(长格式面板数据):
- 股票数量:10 只,代码为 "股票A" 到 "股票J"
- 时间跨度:2020-01-01 到 2023-12-31,仅保留工作日(交易日)
- 数据列:
- date:datetime 类型的日期
- stock_code:字符串类型的股票代码
- close:收盘价(初始价格在 10–100 之间随机,
后续按几何布朗运动模拟,漂移率 0,波动率 0.02)
- volume:成交量(100万到1000万之间的整数)
- return:由 close 计算的日对数收益率
- industry:行业(从「银行」「科技」「消费」「医药」中随机分配,
每只股票固定一个行业)
数据质量模拟:
- 随机插入约 2% 的缺失值(NaN)在 close 和 volume 列
- 随机插入约 0.5% 的极端异常值(超过正常值的 5 倍)在 return 列
输出:
- 数据框命名为 `df`
- 打印前 5 行和基本统计信息(describe())
- 打印每列的缺失值数量
追问模板
模拟数据生成后,我发现以下问题需要修正:
[从以下几种情况选择描述,或自行描述:]
- return 列的值范围不对,出现了大于 1 或小于 -1 的值,
但日收益率不应该有这么大的波动,请检查计算逻辑
- industry 列的分布不均匀,某个行业占了 80% 以上,
请修改为更均匀的随机分配
- 日期列包含了周末,请修改为只保留工作日
请在原有代码基础上修复以上问题,其余部分不变。A4.2 读取数据文件
提示词:读取各类格式的数据文件
这组提示词覆盖了金融分析中最常见的数据文件格式,可按需选取对应部分。
请帮我写 Python 代码,分别读取以下格式的数据文件并存为 pandas 数据框。
每种格式独立一段代码,附中文注释。
1. 【CSV 文件】路径:../data/raw/stock_data.csv
- 编码格式为 GBK(中文 Windows 导出的 CSV 常见编码)
- 第一行为列名
- 读取时直接将 date 列解析为 datetime 类型
2. 【Excel 文件】路径:../data/raw/financial_report.xlsx
- 读取名为「资产负债表」的工作表(sheet)
- 跳过前 2 行(前两行是说明文字,不是数据)
- 只读取第 A 到 G 列
3. 【批量合并多个 CSV 文件】
- ../data/raw/ 目录下有多个以 stock_ 开头的 CSV 文件
- 将所有文件读取后纵向拼接(concat)为一个数据框
- 新增一列 source_file 记录每行数据来自哪个文件名
- 用 tqdm 显示合并进度
追问模板
读取 CSV 文件后出现以下问题,请帮我修复:
[从以下几种情况选择,或自行描述:]
- 报错:UnicodeDecodeError,请帮我尝试其他编码格式(UTF-8、GBK、GB18030)
- 日期列虽然指定了 parse_dates,但读入后仍然是字符串类型,
请检查 date 列的原始格式并用 pd.to_datetime() 手动转换
- 数字列(如 close)读入后变成了字符串,
原因可能是原始数据中含有逗号(如 1,200.50),请处理后转为 floatA4.3 数据探索(EDA)
在清洗之前,先用 AI 帮你生成一份数据「体检报告」,全面了解数据质量,再有针对性地清洗。
提示词:全面的数据质量检查
我有一个 pandas 数据框 `df`,来自 Wind 金融数据库,
是 A 股股票的日度交易数据。
请帮我写代码生成一份数据质量检查报告,包括:
基本信息:
1. 数据框的行数、列数
2. 每列的数据类型(dtypes)
3. 内存占用大小
缺失值分析:
4. 每列的缺失值数量和缺失比例,按缺失比例降序排列
5. 可视化:用 seaborn 热图(heatmap)展示哪些行有缺失
数值列分析:
6. 数值列的描述性统计:均值、中位数、标准差、最小值、最大值、
1% 和 99% 分位数
7. 用箱线图(boxplot)展示数值列的分布,识别异常值
时间序列完整性检查(date 列为 datetime 类型):
8. 数据的起止日期
9. 是否存在同一只股票在同一天有多条记录(重复行)
10. 每只股票的数据条数是否大致相同(是否有股票数据严重缺失)
图形要求:中文标题,图形尺寸 (12, 8),风格使用 seaborn 的 whitegrid。
追问模板——发现问题后进一步定位
数据质量检查发现了以下问题,请帮我进一步定位:
问题 1:close 列有 3.2% 的缺失值,远高于其他列。
请找出缺失值集中在哪些股票、哪些时间段,
并打印出缺失行的 stock_code 和 date,判断是否有规律
(如某只股票停牌期间缺失)。
问题 2:发现了 [X] 条重复的股票-日期组合,
请打印出这些重复行,判断是否是完全相同的记录(可以直接删除)
还是同一天有不同来源的数据(需要进一步处理)。A4.4 数据清洗
A4.4.1 处理缺失值
提示词:缺失值处理策略
我有一个股票日度面板数据框 `df`(10只股票,约1000个交易日),
包含 date、stock_code、close、volume、return 列,
其中 close 列有约 2% 的缺失值(来自停牌日)。
请帮我分别实现以下缺失值处理方案,每个方案独立成一段代码:
1. 【前向填充】对 close 列用前向填充(ffill):
用上一个交易日的收盘价填充缺失日的价格。
注意:必须先按 stock_code 和 date 排序,
再在每只股票内部单独做前向填充(不能跨股票填充)。
结果存为 `df_ffill`
2. 【删除缺失行】直接删除 close 列有缺失的行。
结果存为 `df_drop`
3. 【分组均值填充】用该股票所有交易日的平均收盘价填充缺失值。
按 stock_code 分组计算均值后填充。
结果存为 `df_mean`
对每种方案,处理完后打印:处理前后的缺失值数量,以及数据框的行数变化。
最后,请说明:在金融时间序列分析中,这三种方案各自适合什么场景,
以及哪种方案最常用。
追问模板
前向填充(ffill)代码运行后,close 列仍有 [X] 个缺失值没有被填充。
我猜测原因是某些股票的第一个交易日就是缺失值(没有前一天的数据可以填充)。
请帮我:
1. 确认这个猜测是否正确(打印仍然缺失的行)
2. 对这些无法前向填充的缺失值,改用后向填充(bfill)处理
3. 如果仍有缺失,则直接删除这些行A4.4.2 处理异常值
提示词:识别与处理异常值(Winsorize)
我有一个股票日收益率数据框 `df`,其中 `return` 列包含一些极端异常值
(可能来自数据错误或停复牌导致的异常涨跌)。
请帮我写代码:
1. 【识别异常值】用两种方法识别 return 列的异常值:
- 方法一:超过均值 ±3 个标准差的值
- 方法二:超过 1% 和 99% 分位数的值(Winsorize 法)
分别打印两种方法识别出的异常值数量
2. 【可视化对比】绘制处理前后的收益率分布直方图(并排两图),
x 轴范围固定为 [-0.2, 0.2],便于对比
3. 【Winsorize 处理】
按 stock_code 分组,对每只股票的 return 列分别做 Winsorize:
将超过该股票 1% 分位数的值替换为 1% 分位数,
将低于 99% 分位数的值替换为 99% 分位数。
结果覆盖原 return 列,并新增列 return_raw 保存原始值
4. 处理后打印:被修改的行数,以及修改前后 return 列的极值对比
请说明:为什么按股票分组做 Winsorize,而不是对全样本整体处理?A4.5 数据合并
提示词:合并行情数据与财务数据
这是金融实证研究中最典型的数据合并场景:将日度价格数据与年度财务数据按「股票代码 + 年份」对齐合并。
我有两个 pandas 数据框需要合并:
数据框1:df_price(股票日度行情数据)
- 列:date(datetime)、stock_code(str)、close(float)、return(float)
- 数据量:约 50 万行
数据框2:df_fundamental(公司年度财务数据)
- 列:year(int,如 2020、2021)、stock_code(str)、
roe(float)、leverage(float)、size(float)
- 数据量:约 5000 行
合并需求:
1. 从 df_price 的 date 列提取年份,新增列 year(整数类型)
2. 以 stock_code 和 year 为键,将两个数据框做左连接(left join):
保留 df_price 的所有行,匹配 df_fundamental 中对应的财务数据
3. 合并后检查:有多少行在 df_fundamental 中找不到匹配?
这些行的 stock_code 和 year 是什么?
4. 对合并结果按 stock_code 和 date 升序排列
请同时简要说明 left join、inner join、right join 的区别。
追问模板——合并后行数异常
这是合并操作最常见的陷阱:合并后行数比预期多,说明存在多对多匹配。
df_price 和 df_fundamental 合并后,数据框的行数从 500,000 行
变成了 580,000 行,比预期多了 80,000 行。
请帮我诊断原因:
1. 检查 df_fundamental 中是否有同一个 stock_code + year 组合出现了多次
(即财务数据中有重复记录)
2. 如果存在重复,请帮我在合并前先对 df_fundamental 去重,
保留每个 stock_code + year 组合的最后一条记录
3. 去重后重新合并,确认行数恢复正常A4.6 从金融数据库获取数据
提示词:用 yfinance 获取美股数据
适用于获取美股、港股、ETF 等数据的场景。
请帮我用 yfinance 库下载股票数据,要求:
1. 下载苹果(AAPL)、谷歌(GOOGL)、微软(MSFT)三只股票
从 2020-01-01 到 2024-12-31 的日度数据
2. 获取字段:开盘价、最高价、最低价、调整后收盘价、成交量
3. 将三只股票的数据整合为长格式数据框
(列:date、ticker、open、high、low、adj_close、volume)
4. 计算每只股票的日对数收益率(log return),存为新列 log_return
5. 保存为 CSV 文件:../data/raw/us_stock_daily.csv
异常处理:
- 如果某只股票下载失败,跳过并打印错误信息,不中断整体流程
- 用 tqdm 显示下载进度
提示词:用 WindPy 获取 A 股数据
适用于有 Wind 金融终端权限的场景。
请帮我用 WindPy(Wind Python API)获取 A 股数据。
Wind 终端已在本机登录,Python 环境中已安装 WindPy。
任务1:获取沪深300成分股列表
- 获取当前沪深300(000300.SH)的所有成分股代码
- 使用 w.wset("indexconstituent", ...)
任务2:获取个股日度行情数据
- 股票:平安银行(000001.SZ)
- 时间:2022-01-01 到 2023-12-31
- 字段:收盘价(close)、成交量(volume)、换手率(turn)、市盈率(pe_ttm)
- 使用 w.wsd(...)
任务3:将获取的数据转换为 pandas 数据框:
- 整理列名(去除多余空格,改为英文小写)
- date 列转换为 datetime 类型
请在代码中说明:
- 每次调用 Wind API 后,如何检查返回是否成功(ErrorCode == 0)
- 如果 ErrorCode 不为 0,如何打印错误原因并终止执行