4. Pandas数据分析基础:Series与DataFrame、数据索引与选择、数据合并与连接、分组与聚合操作、时间序列数据处理
做量化交易,说白了就是跟数据打交道。K线数据、订单簿、财务指标……这些数据进了Python,最终都会变成Pandas里的两种核心结构——Series和DataFrame。我刚开始接触量化时,觉得Pandas就是个加强版的Excel,后来踩了不少坑才明白,它的设计哲学远比Excel要深。
4.1 Series与DataFrame:从一维到二维
Series就是一列带标签的数据。你可以把它想象成一个字典,但比字典更灵活。我习惯把Series叫做“带索引的数组”。
import pandas as pd
import numpy as np
# 创建一个Series
s = pd.Series([100, 102, 101, 105], index=['2024-01-01', '2024-01-02', '2024-01-03', '2024-01-04'])
print(s)
DataFrame则是多列Series拼起来的表格。每一列可以有不同的数据类型——价格是浮点数,成交量是整数,股票代码是字符串。这在量化场景里太常见了。
# 创建一个DataFrame
data = {
'open': [100, 102, 101, 105],
'high': [103, 104, 103, 108],
'low': [99, 101, 100, 104],
'close': [102, 101, 105, 107],
'volume': [10000, 12000, 11000, 15000]
}
df = pd.DataFrame(data, index=['2024-01-01', '2024-01-02', '2024-01-03', '2024-01-04'])
print(df)
4.2 数据索引与选择:别再用Excel的思维了
刚转Python时,我总想着用行号去取数据。但在Pandas里,标签索引才是王道。
Pandas提供了两种索引方式:
- loc:基于标签名选择
- iloc:基于整数位置选择
# loc:按标签取
print(df.loc['2024-01-02']) # 取某一行
print(df.loc['2024-01-02', 'close']) # 取某个单元格
# iloc:按位置取
print(df.iloc[1]) # 第二行
print(df.iloc[1, 3]) # 第二行第四列
# 布尔索引:筛选出收盘价大于102的行
print(df[df['close'] > 102])
df[df['close'] > 102]['volume'] = 0)去修改数据。这会产生一个副本,原数据根本没变。后来我改用df.loc[df['close'] > 102, 'volume'] = 0,才彻底解决。
4.3 数据合并与连接:把碎片拼起来
量化交易中,数据很少是完整的。你可能需要把不同时间段的K线拼起来,或者把股票数据和财务数据合并。Pandas提供了三种主要方式:
| 方法 | 用途 | 类比SQL |
|---|---|---|
| concat | 简单拼接,按行或按列 | UNION ALL |
| merge | 类似数据库的JOIN | JOIN |
| join | 基于索引的合并 | 索引JOIN |
# concat:把两个时间段的数据拼起来
df1 = pd.DataFrame({'close': [100, 102]}, index=['2024-01-01', '2024-01-02'])
df2 = pd.DataFrame({'close': [103, 105]}, index=['2024-01-03', '2024-01-04'])
combined = pd.concat([df1, df2])
# merge:类似SQL的inner join
fundamentals = pd.DataFrame({
'stock': ['AAPL', 'GOOGL'],
'pe_ratio': [25, 30]
})
prices = pd.DataFrame({
'stock': ['AAPL', 'GOOGL', 'MSFT'],
'close': [150, 140, 300]
})
merged = pd.merge(prices, fundamentals, on='stock', how='left')
df.duplicated()检查一下,能省很多事。
4.4 分组与聚合操作:从细节看全局
量化分析中,我们经常需要按股票、按行业、按月份做统计。groupby就是干这个的。
# 按股票代码分组,计算每只股票的平均收盘价
df_grouped = df.groupby('stock')['close'].mean()
# 多级分组:按行业和年份
df_multi = df.groupby(['sector', 'year']).agg({
'close': ['mean', 'std'],
'volume': 'sum'
})
你想想看,如果不用groupby,你得写多少循环?Pandas的groupby背后用的是C语言实现的哈希分组,速度比纯Python循环快几十倍。
4.5 时间序列数据处理:量化交易的核心
量化交易的数据,90%以上都是时间序列。Pandas对时间序列的支持,是我选择它的最大原因。
重采样(resample)是最常用的操作。把1分钟K线变成5分钟K线,或者把日线变成周线,一行代码搞定。
# 生成1分钟K线数据
idx = pd.date_range('2024-01-01', periods=100, freq='1min')
ts = pd.Series(np.random.randn(100), index=idx)
# 重采样为5分钟K线,取收盘价
resampled = ts.resample('5min').last()
# 计算滚动均值
rolling_mean = ts.rolling(window=5).mean()
时间偏移在策略回测中也很常见。比如计算过去20天的平均成交量:
# 计算过去5天的滚动平均成交量
df['volume_ma5'] = df['volume'].rolling(window=5).mean()
# 计算收益率(shift用于对齐)
df['return'] = df['close'].pct_change()
# 计算未来5天的最高价(shift(-5))
df['future_high_5'] = df['high'].shift(-5).rolling(window=5).max()
shift(-1)去预测第二天的涨跌,结果回测曲线漂亮得不像话,实盘却亏得一塌糊涂。后来才发现,shift(-1)泄露了未来信息。
知识体系总览
下面这张图,是我自己总结的Pandas在量化交易中的核心脉络。你可以把它当作一个速查地图:
嗯,这张图基本把本章的核心内容串起来了。从数据结构出发,到数据操作,最后落到时间序列这个量化交易的核心场景。你可以在实际项目中,对照这张图去梳理自己的数据处理流程。
总结一下:Series和DataFrame是基础,索引选择是日常操作,合并连接是数据整合的关键,分组聚合是统计分析的利器,时间序列处理则是量化交易的灵魂。把这五块吃透了,Pandas这块就算入门了。