Appearance
Python数据处理进阶:排序、分组、统计
为什么要学这个
在量化投资中,你经常需要处理大量股票数据,比如:
- "今天A股涨幅前10名是哪些?" → 排序排名
- "按行业分组,各行业平均PE是多少?" → 分组统计
- "这50只股票的平均收益是多少?波动大不大?" → 统计概念
这些操作用pandas库就能搞定。本文帮你掌握这三个核心技能。
一、排序和排名
1.1 按涨幅排名
假设你有一组股票数据,想按涨幅排序:
python
import pandas as pd
# 模拟一组股票数据
data = {
'股票代码': ['600519', '000858', '600887', '603288', '000333'],
'股票名称': ['贵州茅台', '五粮液', '伊利股份', '海天味业', '美的集团'],
'今日涨幅': [2.5, -1.2, 3.8, 0.5, 1.7]
}
df = pd.DataFrame(data)
# 按涨幅从高到低排序
df_sorted = df.sort_values('今日涨幅', ascending=False)
print(df_sorted)输出:
股票代码 股票名称 今日涨幅
2 600887 伊利股份 3.8
0 600519 贵州茅台 2.5
4 000333 美的集团 1.7
3 603288 海天味业 0.5
1 000858 五粮液 -1.2关键代码就是一行:df.sort_values('列名', ascending=False)
ascending=False表示从大到小(降序)ascending=True或不写,表示从小到大(升序)
1.2 排名
有时候你不需要改变顺序,只需要知道每只股票排第几:
python
# 添加一列"涨幅排名"
df['涨幅排名'] = df['今日涨幅'].rank(ascending=False, method='min')
print(df[['股票名称', '今日涨幅', '涨幅排名']])输出:
股票名称 今日涨幅 涨幅排名
0 贵州茅台 2.5 2.0
1 五粮液 -1.2 5.0
2 伊利股份 3.8 1.0
3 海天味业 0.5 4.0
4 美的集团 1.7 3.01.3 选前N名
量化选股中经常要选"排名前10"的股票:
python
# 涨幅前3名
top3 = df.nlargest(3, '今日涨幅')
print(top3[['股票名称', '今日涨幅']])输出:
股票名称 今日涨幅
2 伊利股份 3.8
0 贵州茅台 2.5
4 美的集团 1.7二、分组统计
2.1 按行业分组
假设你有多只股票的数据,想知道每个行业的平均PE:
python
data = {
'股票名称': ['贵州茅台', '五粮液', '伊利股份', '海天味业', '千禾味业'],
'行业': ['白酒', '白酒', '乳制品', '调味品', '调味品'],
'PE': [35, 25, 20, 55, 45],
'ROE': [0.31, 0.25, 0.24, 0.30, 0.15]
}
df = pd.DataFrame(data)
# 按行业分组,计算平均PE
result = df.groupby('行业')['PE'].mean()
print(result)输出:
行业
乳制品 20.0
白酒 30.0
调味品 50.0就这样,一行代码就能按行业分组统计。
2.2 多个统计量
想一次看多个统计结果:
python
# 按行业分组,同时看PE的均值、最大值、最小值
result = df.groupby('行业')['PE'].agg(['mean', 'max', 'min'])
print(result)输出:
mean max min
行业
乳制品 20.0 35 20
白酒 30.0 35 25
调味品 50.0 55 452.3 按多列分组
想同时按行业和另一个条件分组:
python
# 先按行业分组,每组内按PE排序
df['行业PE排名'] = df.groupby('行业')['PE'].rank(ascending=True)
print(df[['股票名称', '行业', 'PE', '行业PE排名']])这在因子分析中非常有用——你可以把股票按行业分组,然后在每个行业内排名,消除行业差异的影响。
三、基本统计概念
不用公式,用数字例子来理解。
3.1 均值(平均数)
含义:一组数的"平均水平"。
python
# 5只股票的年收益率
returns = [15, -5, 22, 8, -12]
average = sum(returns) / len(returns) # 手算:5.6%
# 或者用pandas
# pd.Series(returns).mean() # 也是5.6%均值告诉你"这组股票平均赚了多少"。
3.2 标准差(波动大小)
含义:数据围绕均值的"分散程度"。标准差越大,波动越大。
python
import numpy as np
# 策略A的月度收益:稳定赚钱
strategy_a = [2, 3, 1, 2, 3, 2, 1, 3, 2, 2] # 标准差小,稳定
# 策略B的月度收益:大起大落
strategy_b = [10, -8, 15, -12, 8, -5, 20, -15, 12, -3] # 标准差大,波动
print(f"策略A 均值={np.mean(strategy_a):.1f}%, 标准差={np.std(strategy_a):.1f}%")
print(f"策略B 均值={np.mean(strategy_b):.1f}%, 标准差={np.std(strategy_b):.1f}%")输出(大约):
策略A 均值=2.1%, 标准差=0.7%
策略B 均值=2.2%, 标准差=11.7%两个策略均值差不多,但策略B的波动大得多。同样的平均收益,波动越小越好。
3.3 相关系数(涨跌同步性)
含义:两组数据是否"同涨同跌"。相关系数在-1到1之间。
python
# 股票A和股票B的5天涨跌
stock_a = [2, -1, 3, -2, 1] # A的涨跌
stock_b = [1.5, -0.8, 2.5, -1.5, 0.8] # B的涨跌跟A很像
stock_c = [-1, 2, -2, 3, -0.5] # C的涨跌跟A相反
corr_ab = np.corrcoef(stock_a, stock_b)[0, 1] # 接近1,高度正相关
corr_ac = np.corrcoef(stock_a, stock_c)[0, 1] # 接近-1,负相关
print(f"A和B的相关系数: {corr_ab:.2f}") # ≈ 0.99
print(f"A和C的相关系数: {corr_ac:.2f}") # ≈ -0.95| 相关系数 | 含义 | 投资意义 |
|---|---|---|
| 接近1 | 高度同涨同跌 | 分散风险效果差 |
| 接近0 | 没有线性关系 | 分散风险效果好 |
| 接近-1 | 涨跌相反 | 完美对冲 |
四、简单线性关系铺垫
4.1 直觉理解
生活中很多变量之间有线性关系:
- 身高越高,鞋码通常越大
- 学习时间越长,成绩通常越好
- 公司营收越高,利润通常越多
4.2 用numpy拟合
python
import numpy as np
# 身高(cm)和鞋码的对应数据
height = [160, 165, 170, 175, 180, 185]
shoe_size = [38, 39, 40, 42, 43, 44]
# 拟合一条直线:鞋码 = a * 身高 + b
a, b = np.polyfit(height, shoe_size, 1)
print(f"关系:鞋码 ≈ {a:.2f} × 身高 + ({b:.2f})")
# 大约:鞋码 ≈ 0.24 × 身高 + (-0.40)
# 用这个关系预测:身高178的人大概穿多大鞋?
predicted = a * 178 + b
print(f"预测鞋码:{predicted:.0f}") # 大约42码np.polyfit(x, y, 1)就是"用一条直线来拟合x和y的关系"。最后的1表示"一次方程"(直线)。
这在后面学因子分析时会用到——比如研究"PE和未来收益之间有没有线性关系"。
小结
| 技能 | 关键代码 | 用途 |
|---|---|---|
| 排序 | df.sort_values('列名') | 按某列排序 |
| 排名 | df['列名'].rank() | 不改变顺序,只标排名 |
| 选前N名 | df.nlargest(N, '列名') | 选排名前N的 |
| 分组 | df.groupby('列名') | 按某列分组 |
| 分组统计 | groupby().agg(['mean','max']) | 分组后计算统计量 |
| 均值 | np.mean() | 平均值 |
| 标准差 | np.std() | 波动大小 |
| 相关系数 | np.corrcoef() | 涨跌同步性 |
| 线性拟合 | np.polyfit(x, y, 1) | 找两个变量的线性关系 |
💡 这些工具在后面对因子分析、选股策略、回测评估中都会反复用到。不用死记,用到时回来查就行。
下一篇:策略开发流程