如何用Python DataFrame按年份计算正负收益日的平均收益率?
按年份计算正/负收益日平均收益率的实现方案
你已经完成了数据预处理(计算涨跌幅、标记正负收益日、提取年份),现在要给yearly_data添加每年正收益日和负收益日的平均收益率,可以通过以下几种清晰的方式实现:
方法一:分步计算并合并(逻辑直观)
这种方式适合逐步拆解需求,每一步的作用都很明确:
import csv import pandas as pd import numpy as np # 你的原有预处理代码 stocks_dataframe = pd.read_csv('^GSPC.csv', delimiter = ',') stocks_dataframe['Percent_change'] = stocks_dataframe['Close'].pct_change() stocks_dataframe['positive_return_day'] = np.where(stocks_dataframe['Percent_change']>=0, 1, 0) stocks_dataframe['negative_return_day'] = np.where(stocks_dataframe['Percent_change']<0, 1, 0) stocks_dataframe['date'] = pd.to_datetime(stocks_dataframe['Date']) stocks_dataframe['year'], stocks_dataframe['month'] = stocks_dataframe['date'].dt.year, stocks_dataframe['date'].dt.month # 1. 计算每年正收益日的平均收益率:先过滤正收益日,再按年份取均值 positive_yearly_avg = stocks_dataframe[stocks_dataframe['positive_return_day'] == 1].groupby('year')['Percent_change'].mean() # 2. 计算每年负收益日的平均收益率:过滤负收益日,再按年份取均值 negative_yearly_avg = stocks_dataframe[stocks_dataframe['negative_return_day'] == 1].groupby('year')['Percent_change'].mean() # 3. 整合所有统计量到yearly_data yearly_data = pd.DataFrame({ 'positive_day_count': stocks_dataframe['positive_return_day'].groupby('year').sum(), 'negative_day_count': stocks_dataframe['negative_return_day'].groupby('year').sum(), 'positive_avg_return': positive_yearly_avg, 'negative_avg_return': negative_yearly_avg }).reset_index() # 可选:把year从索引转为普通列,方便后续查看和操作
方法二:用groupby.agg一次性完成(更高效简洁)
如果追求代码简洁性,可以通过聚合函数一次性完成所有统计指标的计算:
# 基于你预处理好的stocks_dataframe直接操作 yearly_data = stocks_dataframe.groupby('year').agg( positive_day_count=('positive_return_day', 'sum'), negative_day_count=('negative_return_day', 'sum'), # 正收益日平均收益率:lambda函数过滤正收益后求均值 positive_avg_return=('Percent_change', lambda x: x[x >= 0].mean()), # 负收益日平均收益率:lambda函数过滤负收益后求均值 negative_avg_return=('Percent_change', lambda x: x[x < 0].mean()) ).reset_index()
关键说明
- 两种方法的结果完全一致,方法二减少了中间变量的创建,运行效率更高。
lambda x: x[x >=0].mean()的作用是:对每个年份的涨跌幅序列,只保留正收益的记录,再计算它们的平均值,就是该年正收益日的平均收益率。- 如果某一年没有正/负收益日,对应列会显示
NaN,你可以根据需求用fillna(0)或其他方式填充。
运行完成后,yearly_data会包含年份、正负收益日数量、正负收益日平均涨跌幅这几类核心数据,完全满足你的需求。
内容的提问来源于stack exchange,提问作者adrCoder
相关产品推荐
相关产品推荐

