Skip to content

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.0

1.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   45

2.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)找两个变量的线性关系

💡 这些工具在后面对因子分析、选股策略、回测评估中都会反复用到。不用死记,用到时回来查就行。


下一篇:策略开发流程

仅供学习交流,不构成任何投资建议