Python中按条件查找最大日期值:基金NAV三月收益率计算
解决方案
首先确保日期列是 datetime 类型,这是时间计算的前提:
import pandas as pd from datetime import timedelta # 转换date列为datetime格式 df['date'] = pd.to_datetime(df['date'])
方法一:分组逐行处理(适合新手理解,小数据量)
这个逻辑和你Excel的数组公式思路一致,先按基金分组,再为每个日期筛选符合条件的最大历史日期:
# 定义处理单只基金数据的函数 def process_fund(group): # 对每个日期,找到该基金下<=当前日期-91天的最大日期 group['prev_max_date'] = group['date'].apply( lambda current_date: group[group['date'] <= current_date - timedelta(days=91)]['date'].max() ) return group # 按基金分组应用函数 df = df.groupby('fund code').apply(process_fund) # 关联三个月前的NAV数据 df = df.merge( df[['fund code', 'date', 'NAV']].rename(columns={'date': 'prev_max_date', 'NAV': 'prev_NAV'}), on=['fund code', 'prev_max_date'], how='left' ) # 计算三月收益率,无匹配数据时显示NaN df['3_month_return'] = (df['NAV'] / df['prev_NAV']) - 1
方法二:用merge_asof高效匹配(大数据量推荐)
如果数据量较大,逐行apply效率较低,merge_asof是pandas专门用于这类向前匹配最近值的工具,性能更优:
# 按基金代码和日期排序(merge_asof要求输入数据已排序) df_sorted = df.sort_values(['fund code', 'date']) # 生成匹配基准:当前日期往前推91天 df_sorted['match_threshold'] = df_sorted['date'] - timedelta(days=91) # 匹配每个基金下,<=match_threshold的最大日期对应的NAV df_merged = pd.merge_asof( df_sorted, df_sorted[['fund code', 'date', 'NAV']].rename(columns={'date': 'prev_date', 'NAV': 'prev_NAV'}), left_on='match_threshold', right_on='prev_date', by='fund code', direction='backward' # 取小于等于阈值的最近日期 ) # 计算收益率 df_merged['3_month_return'] = (df_merged['NAV'] / df_merged['prev_NAV']) - 1
关于你之前代码的问题
你写的 max(filter(lambda x: x<=df['date']-timedelta(days=91))) 存在两个核心问题:
df['date']是整个列的Series,不是单个日期值,无法直接和单个timedelta做减法后做筛选- 没有按基金分组,会把所有基金的日期混在一起计算,逻辑错误
内容的提问来源于stack exchange,提问作者idleriver
相关产品推荐
相关产品推荐

