第3章:Pandas基础与债券数据读取
说实话,刚入行做债券量化那会儿,我最头疼的就是数据读取。交易所的数据格式五花八门,有的用CSV,有的用Excel,还有的直接从Wind导出来带一堆乱码。后来我慢慢摸索出一套套路,今天就跟大家聊聊Pandas处理债券数据的基本功。
3.1 Series与DataFrame:债券数据的两种容器
Pandas里最核心的两个东西,就是Series和DataFrame。你可以把Series想象成一列数据,比如某只债券的每日收盘价序列。DataFrame呢,就是一张完整的表格,行是日期,列是各种字段——开盘价、收盘价、成交量等等。
我刚开始用的时候,老是把它们搞混。后来我记住一句话:Series是一维的,DataFrame是二维的。就这么简单。
核心区别:
- Series:带标签的一维数组,适合存储单个时间序列(如某只债券的日收益率)
- DataFrame:带标签的二维表格,适合存储多只债券或多维度的数据
举个例子,假设我们有一只国债“21国债10”,它的每日收盘价可以存成Series:
import pandas as pd
# 创建一个Series,存储债券收盘价
closing_prices = pd.Series(
[100.25, 100.30, 100.18, 100.42, 100.35],
index=['2024-01-02', '2024-01-03', '2024-01-04', '2024-01-05', '2024-01-08'],
name='21国债10收盘价'
)
print(closing_prices)
输出结果是这样的:
2024-01-02 100.25
2024-01-03 100.30
2024-01-04 100.18
2024-01-05 100.42
2024-01-08 100.35
Name: 21国债10收盘价, dtype: float64
你看,左边是索引(日期),右边是数值(价格),这就是Series的典型结构。我在做回测的时候,经常用Series来存策略的每日净值,方便后面计算收益率和最大回撤。
那DataFrame呢?它更像一张Excel表格。比如我们想存多只债券的行情:
# 创建一个DataFrame,存储多只债券行情
bond_data = pd.DataFrame({
'日期': ['2024-01-02', '2024-01-03', '2024-01-04'],
'21国债10': [100.25, 100.30, 100.18],
'21国债15': [101.10, 101.05, 101.20],
'22国债01': [99.80, 99.75, 99.90]
})
print(bond_data)
日期 21国债10 21国债15 22国债01
0 2024-01-02 100.25 101.10 99.80
1 2024-01-03 100.30 101.05 99.75
2 2024-01-04 100.18 101.20 99.90
嗯,这里要注意一点:DataFrame的每一列其实都是一个Series。所以当你取bond_data['21国债10']时,得到的就是一个Series。这个关系搞清楚了,后面操作起来就顺手多了。
3.2 从CSV读取债券行情数据
实际工作中,债券数据最常见的来源就是CSV文件。交易所每天收盘后会生成一个CSV,里面包含了当天所有债券的行情。我一般用pd.read_csv()来读,但有几个参数必须设对。
先看一个典型的债券行情CSV长什么样:
日期,债券代码,债券简称,收盘价,涨跌幅,成交量
2024-01-02,019640.SH,21国债10,100.25,0.05,50000
2024-01-02,019658.SH,21国债15,101.10,-0.02,32000
2024-01-02,019694.SH,22国债01,99.80,0.10,45000
读取的代码很简单:
import pandas as pd
# 读取CSV文件
df = pd.read_csv('bond_daily_20240102.csv', encoding='utf-8')
print(df.head())
但是!我曾经踩过一个坑——日期列默认会被读成字符串。如果你后面要做时间序列分析,必须把它转成datetime类型:
# 正确做法:指定日期列并解析
df = pd.read_csv(
'bond_daily_20240102.csv',
encoding='utf-8',
parse_dates=['日期'], # 自动解析日期列
index_col='日期' # 把日期列设为索引
)
print(df.info())
避坑指南:我曾经因为没设parse_dates,导致后面画图时日期轴全乱了。还有一次,CSV文件里混了中文逗号(全角),read_csv直接报错。所以建议读取时加上encoding='utf-8-sig',能兼容大部分情况。
3.3 从Excel读取债券数据
有些机构喜欢用Excel存数据,特别是做信用债分析的时候,Excel里经常有多个sheet,每个sheet对应不同评级或不同期限的债券。
读取Excel用pd.read_excel():
# 读取Excel文件
df_excel = pd.read_excel(
'bond_credit_data.xlsx',
sheet_name='AAA级', # 指定sheet
header=0 # 第一行作为列名
)
print(df_excel.shape) # 看看有多少行多少列
如果Excel里有多个sheet,可以用sheet_name=None一次性读进来,返回一个字典:
# 读取所有sheet
all_sheets = pd.read_excel('bond_credit_data.xlsx', sheet_name=None)
# 遍历每个sheet
for sheet_name, df_sheet in all_sheets.items():
print(f"Sheet: {sheet_name}, 行数: {len(df_sheet)}")
我个人习惯用openpyxl引擎来处理Excel,因为它的兼容性最好。如果遇到.xls格式的老文件,记得装xlrd库。
3.4 数据预览与基本信息查看
数据读进来之后,第一件事不是急着分析,而是先看看数据长什么样。我一般会做这几步检查:
3.4.1 快速预览:head()和tail()
# 查看前5行
print(df.head())
# 查看后3行
print(df.tail(3))
head()默认显示前5行,tail()默认显示后5行。你可以传参数指定行数。这个操作能帮你快速判断数据是否正常加载。
3.4.2 基本信息:info()
# 查看数据框基本信息
df.info()
输出类似这样:
<class 'pandas.core.frame.DataFrame'>
DatetimeIndex: 1000 entries, 2024-01-02 to 2024-12-31
Data columns (total 5 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 债券代码 1000 non-null object
1 债券简称 1000 non-null object
2 收盘价 998 non-null float64
3 涨跌幅 1000 non-null float64
4 成交量 1000 non-null int64
dtypes: float64(2), int64(1), object(2)
memory usage: 46.9 KB
这里有几个关键信息:
- 行数和列数:1000行,5列
- 非空值数量:收盘价只有998个非空,说明有2个缺失值
- 数据类型:object一般是字符串,float64是浮点数,int64是整数
小技巧:如果发现某列应该是数值型但显示为object,多半是数据里混了字符(比如“--”表示缺失)。可以用pd.to_numeric()强制转换,错误值设为NaN。
3.4.3 统计描述:describe()
# 查看数值列的统计信息
print(df.describe())
输出:
收盘价 涨跌幅 成交量
count 998.000000 1000.000000 1.000000e+03
mean 100.150000 0.001200 4.200000e+04
std 1.250000 0.015000 1.500000e+04
min 97.500000 -0.050000 1.000000e+04
25% 99.200000 -0.008000 3.000000e+04
50% 100.100000 0.001000 4.000000e+04
75% 101.000000 0.010000 5.200000e+04
max 103.500000 0.060000 8.000000e+04
这个表能告诉你数据的分布情况。比如收盘价最低97.5,最高103.5,均值100.15。如果发现最大值异常高,那就要警惕是不是数据录入错误。
3.4.4 缺失值检查:isnull()
# 检查每列的缺失值数量
print(df.isnull().sum())
# 缺失值占比
print(df.isnull().mean() * 100)
我记得有一次做国债期货分析,发现某天的数据全是NaN。后来查出来是交易所那天休市,但数据文件还是生成了。所以检查缺失值是个好习惯,能避免后面计算时出现莫名其妙的错误。
3.5 本章知识体系
下面这张图总结了本章的核心内容,你可以把它当作一个快速索引:
嗯,到这里Pandas的基础操作就讲完了。说白了就是三板斧:读进来、看一眼、查问题。后面几章我们会在这个基础上做更复杂的操作,比如数据清洗、合并、分组聚合等等。但今天这些基本功,是后面所有操作的地基。
我个人建议你找个真实的债券CSV文件练练手。没有的话,可以用pd.DataFrame()自己造点数据。多试几次,手感就来了。
公众号:蓝海资料掘金营,微信deep3321