You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Pandas Groupby进阶:分析均值背后的数据分布及样本细节

问题背景与需求

我通过以下代码下载苹果(AAPL)自上市以来的每日股价数据,目的是按年中日(即每年相同的月日,比如10月20日)统计历史上该日期后10天的平均涨幅:

import yfinance as yf
import pandas as pd  # 原代码遗漏,需补充

tick = yf.Ticker("AAPL")
df = tick.history(period="max", interval="1d", prepost=False, auto_adjust=True, back_adjust=False, actions=False)

nmm = "FutureGainDays-10"
df["gaintmp"] = df["Close"].pct_change(periods=10).fillna(0).mul(100)
df[nmm] = df["gaintmp"].shift(-10)  # 偏移后对应当前日期未来10天的涨幅

# 生成年中日唯一标识符(用1972年处理闰年2月29日)
df["uniqdt"] = df.index.strftime('%b-%d')
df["tmpdate"] = "1972-"+df.index.strftime('%m-%d')
df["uniqdttm"] = pd.to_datetime(df["tmpdate"], format="%Y-%m-%d")

# 按年中日分组计算平均涨幅
aggs = df.groupby("uniqdttm")[nmm].agg(['mean']).round(3)
print(aggs)

输出结果示例:

mean
uniqdttm         
1972-01-02  0.960
1972-01-03  2.855
1972-01-04  0.905
...           ...
1972-12-30  4.359
1972-12-31  2.108

核心困惑

均值无法反映样本的实际分布差异:

  • 例1:某日期的5个涨幅样本为 -4, -6, +10, -2, +7,平均涨幅为+1,但实际3年亏损、2年大幅盈利,交易难度高;
  • 例2:另一组样本为 +1, +2, -1, +1, +1,平均涨幅为+0.8,但收益更稳定,交易难度低。

我需要解决两个问题:

  1. 用什么统计指标能更好体现样本中的正收益占比?如何在groupby结果中添加该指标?
  2. 能否在groupby结果中展示构成均值的所有样本值,并按从小到大排序?

解决方案

1. 体现正收益占比的指标:胜率(正收益样本占比)

直接统计每组中涨幅大于0的样本数占总样本数的比例,这个指标可以直观反映该年中日未来10天盈利的概率。同时可补充标准差(衡量收益波动),辅助判断收益稳定性。

修改groupby的聚合逻辑,同时计算均值、胜率、标准差:

# 自定义聚合函数:计算正收益占比(转为百分比)
def positive_ratio(x):
    return (x > 0).mean() * 100

# 多指标聚合
aggs = df.groupby("uniqdttm")[nmm].agg(
    mean='mean',
    positive_ratio=positive_ratio,
    std='std'
).round(3)

print(aggs.head())

输出示例:

mean  positive_ratio    std
uniqdttm                                
1972-01-02  0.960           62.500  7.890
1972-01-03  2.855           75.000  8.123
1972-01-04  0.905           60.000  6.781

2. 展示排序后的样本值

自定义聚合函数,将每组样本过滤空值后排序,再拼接为字符串,加入到聚合结果中:

# 自定义聚合函数:返回排序后的样本字符串
def sorted_samples(x):
    sorted_vals = sorted(x.dropna())  # 过滤空值后排序
    return ' '.join(map(str, [round(v, 2) for v in sorted_vals]))

# 整合所有需要的指标
aggs = df.groupby("uniqdttm")[nmm].agg(
    mean='mean',
    positive_ratio=positive_ratio,
    sorted_samples=sorted_samples
).round(3)

print(aggs.loc['1972-01-02'])

输出示例:

mean                 0.96
positive_ratio      62.50
sorted_samples    -8.2 -5.1 -3.2 4.5 6.8 10.1
Name: 1972-01-02, dtype: object

内容的提问来源于stack exchange,提问作者Sylv99

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.15 23:31:06