如何按年份分组DataFrame并计算DailyChange列的几何均值?
按年份计算每日价格变动的几何均值问题
代码分析与问题排查
1. 分组逻辑验证
你的分组逻辑是正确的:
pd.Grouper(key="data", freq="Y")会按自然年对日期列分组,默认返回每年的最后一天作为分组标签(比如2023年的分组标签是2023-12-31)- 后续通过
dt.year提取年份,最终得到以年份为标识的分组结果,这部分没有问题。
2. stats.gmean 使用注意事项
这里需要注意两个核心点:
几何均值的输入限制:
scipy.stats.gmean要求所有输入值必须为正数,因为几何均值基于数值乘积开方计算,0或负数会导致计算错误或无意义结果。变动率的转换逻辑:如果你的
DailyChange是百分比形式(比如-5代表下跌5%,+3代表上涨3%),当前的x.dropna() + 100是把变动率转成100+变动值(比如-5→95),这种转换本身可行,但要确保DailyChange > -100,否则x+100会≤0,触发gmean报错。更符合行业惯例的转换方式是将变动率转成增长因子:
1 + x.dropna()/100(比如-5%→0.95,+3%→1.03),计算几何均值后再转回百分比:(gmean_result - 1)*100,两种方式结果一致,但增长因子的形式更直观易懂。
3. 可能的问题触发点
如果代码运行报错或结果不符合预期,大概率是以下情况:
- 存在
DailyChange ≤ -100的异常值,导致x+100≤0,gmean无法计算 - 某年份的
DailyChange全部为缺失值,x.dropna()后为空序列,触发计算错误
修正后的代码示例
针对上述问题,可加入异常值过滤和空值判断:
import pandas as pd from scipy import stats df = pd.read_csv("data_with_changes.csv") df["data"] = pd.to_datetime(df["data"]) def calc_geo_mean(x): # 过滤掉会导致增长因子<=0的异常值 valid_values = x.dropna() valid_values = valid_values[valid_values > -100] if len(valid_values) == 0: return None # 无有效数据时返回空值 # 用增长因子计算几何均值 growth_factors = 1 + valid_values / 100 geo_mean_factor = stats.gmean(growth_factors) return (geo_mean_factor - 1) * 100 df_result = df.groupby(pd.Grouper(key="data", freq="Y"))["DailyChange"].apply(calc_geo_mean).reset_index() df_result.columns = ["Year", "GeometricMean"] df_result["Year"] = df_result["Year"].dt.year df_result.to_csv("average_daily_change.csv", index=False)
内容的提问来源于stack exchange,提问作者Jiri
相关产品推荐
相关产品推荐

