4. Pandas基础:Series与DataFrame、数据读取与写入、索引与选择、缺失值处理
好,咱们进入量化金融最核心的数据处理工具——Pandas。说实话,我见过不少新手,一上来就急着跑模型,结果数据清洗就卡了三天。Pandas就是那个让你少加班的利器。
我个人习惯把Pandas比作「Excel的超级升级版」。你想想看,Excel处理10万行数据就卡得不行,Pandas处理百万级数据跟玩似的。而且,它能跟Python的数学库无缝衔接,这才是关键。
4.1 Series与DataFrame:两种核心数据结构
Pandas里就两种核心结构:Series和DataFrame。说白了,Series就是一列数据,DataFrame就是多列数据组成的表格。
4.1.1 Series:一维数据容器
Series就像带标签的数组。每个元素都有索引,默认是0、1、2...但你可以自定义。
import pandas as pd
import numpy as np
# 从列表创建Series
s = pd.Series([100, 200, 300, 400, 500])
print(s)
# 输出:
# 0 100
# 1 200
# 2 300
# 3 400
# 4 500
# dtype: int64
# 自定义索引
s_with_index = pd.Series([100, 200, 300], index=['a', 'b', 'c'])
print(s_with_index)
# a 100
# b 200
# c 300
# dtype: int64
我在项目中遇到过一个问题:用字典创建Series时,键会自动变成索引。这个特性在构建股票代码映射表时特别有用。
# 从字典创建
stock_prices = {'AAPL': 175.30, 'GOOGL': 140.50, 'MSFT': 330.20}
s = pd.Series(stock_prices)
print(s)
# AAPL 175.30
# GOOGL 140.50
# MSFT 330.20
# dtype: float64
4.1.2 DataFrame:二维表格结构
DataFrame才是咱们真正的主力。它由多个Series组成,每个Series是一列。你可以把它想象成一个带行索引和列索引的Excel表格。
# 从字典创建DataFrame
data = {
'股票代码': ['AAPL', 'GOOGL', 'MSFT', 'AMZN'],
'收盘价': [175.30, 140.50, 330.20, 145.80],
'成交量': [50000000, 25000000, 35000000, 40000000],
'日期': ['2024-01-15', '2024-01-15', '2024-01-15', '2024-01-15']
}
df = pd.DataFrame(data)
print(df)
# 股票代码 收盘价 成交量 日期
# 0 AAPL 175.30 50000000 2024-01-15
# 1 GOOGL 140.50 25000000 2024-01-15
# 2 MSFT 330.20 35000000 2024-01-15
# 3 AMZN 145.80 40000000 2024-01-15
4.2 数据读取与写入:跟文件打交道
做量化金融,数据来源无非是CSV、Excel、数据库。Pandas提供了统一的接口,让你不用关心底层文件格式。
4.2.1 读取CSV文件
CSV是最常见的格式。我建议你养成一个好习惯:读取时指定数据类型,能省去后面很多麻烦。
# 基础读取
df = pd.read_csv('stock_data.csv')
# 指定数据类型(推荐)
df = pd.read_csv(
'stock_data.csv',
dtype={'股票代码': str, '收盘价': float, '成交量': int},
parse_dates=['日期'], # 自动解析日期
index_col='日期' # 用日期列做索引
)
# 只读取前1000行(预览数据时用)
df_sample = pd.read_csv('stock_data.csv', nrows=1000)
4.2.2 读取Excel文件
Excel文件需要额外安装openpyxl或xlrd库。我个人偏爱openpyxl,因为它支持.xlsx格式。
# 读取Excel
df = pd.read_excel('stock_data.xlsx', sheet_name='Sheet1')
# 读取多个sheet
sheets = pd.read_excel('stock_data.xlsx', sheet_name=None)
# 返回一个字典,键是sheet名,值是DataFrame
4.2.3 写入文件
处理完数据后,保存结果也很简单。
# 保存为CSV
df.to_csv('processed_stock_data.csv', index=False)
# 保存为Excel
df.to_excel('processed_stock_data.xlsx', sheet_name='清洗后数据', index=False)
index=False,否则Pandas会把行索引也写进文件,导致多出一列没用的数据。
4.3 索引与选择:精准定位数据
数据读进来了,怎么取数据?Pandas提供了两种索引方式:基于标签的loc和基于位置的iloc。嗯,这里要注意区分。
4.3.1 使用loc按标签选择
# 假设df的索引是日期
df = pd.read_csv('stock_data.csv', index_col='日期', parse_dates=['日期'])
# 选择某一行
row = df.loc['2024-01-15']
# 选择多行
rows = df.loc['2024-01-15':'2024-01-20']
# 选择某几列
cols = df.loc[:, ['收盘价', '成交量']]
# 同时选择行和列
subset = df.loc['2024-01-15':'2024-01-20', ['收盘价', '成交量']]
4.3.2 使用iloc按位置选择
# 选择第一行
first_row = df.iloc[0]
# 选择前5行
first_5 = df.iloc[:5]
# 选择第一列
first_col = df.iloc[:, 0]
# 选择第1到第3行,第0到第2列
subset = df.iloc[0:3, 0:2]
4.3.3 布尔索引:条件筛选
这是我最常用的方式。你想筛选出所有收盘价大于200的股票,一行代码搞定。
# 筛选收盘价大于200的股票
high_price = df[df['收盘价'] > 200]
# 多条件筛选
filtered = df[(df['收盘价'] > 200) & (df['成交量'] > 30000000)]
# 使用query方法(更简洁)
filtered = df.query('收盘价 > 200 and 成交量 > 30000000')
4.4 缺失值处理:数据清洗的核心
真实数据永远不完美。缺失值就是最常见的「脏数据」。我处理过的股票数据里,节假日、停牌日都会产生缺失值。
4.4.1 检测缺失值
# 检查哪些值是缺失的
print(df.isnull())
# 统计每列的缺失值数量
print(df.isnull().sum())
# 查看缺失值占比
print(df.isnull().mean() * 100)
4.4.2 删除缺失值
# 删除包含任何缺失值的行
df_clean = df.dropna()
# 删除某列有缺失值的行
df_clean = df.dropna(subset=['收盘价'])
# 删除全部为缺失值的行
df_clean = df.dropna(how='all')
# 删除缺失值超过50%的列
df_clean = df.dropna(thresh=len(df) * 0.5, axis=1)
4.4.3 填充缺失值
填充方式取决于业务场景。股票数据我一般用前向填充或插值。
# 用固定值填充
df['收盘价'] = df['收盘价'].fillna(0)
# 用均值填充
df['收盘价'] = df['收盘价'].fillna(df['收盘价'].mean())
# 前向填充(用上一个有效值填充)
df['收盘价'] = df['收盘价'].fillna(method='ffill')
# 后向填充
df['收盘价'] = df['收盘价'].fillna(method='bfill')
# 插值法(线性插值)
df['收盘价'] = df['收盘价'].interpolate(method='linear')
4.4.4 高级技巧:条件填充
# 只填充连续缺失不超过3天的数据
def fill_limited_missing(series, max_gap=3):
# 标记连续缺失的组
groups = series.isnull().astype(int).groupby(series.notnull().cumsum()).cumsum()
# 只填充连续缺失不超过max_gap的
series_filled = series.where(groups > max_gap, series.fillna(method='ffill'))
return series_filled
df['收盘价'] = fill_limited_missing(df['收盘价'], max_gap=3)
这个函数是我在实盘项目中写的。连续停牌超过3天的股票,我会标记为异常,而不是盲目填充。你想想看,如果一只股票连续停牌一周,用前向填充显然不合理。
知识体系总览
下面这张图总结了本章的核心内容,方便你回顾。
好了,这一章的内容就到这里。Pandas基础是量化金融的「基本功」,你花时间把它练扎实了,后面跑模型的时候会特别顺畅。记住我上面提到的那些坑,能帮你少走不少弯路。