基于条件的DataFrame滚动10年均价计算及Pandas索引报错求助
问题解决:DataFrame条件均值计算与索引报错修复
我来帮你逐个搞定这两个问题——先解决你遇到的iloc索引报错,再处理核心的10年价格均值计算+标识列需求。
一、修复ValueError:iloc索引使用错误
这个报错的原因很直观:iloc是基于整数位置的索引工具,你传入了datetime对象(date1)和列名字符串,完全不符合它的参数要求,所以触发了 ValueError。
修正方案
根据你的数据结构,分两种情况处理:
情况1:df_dates2的索引是日期类型
如果你的DataFrame已经把日期设为索引,直接用loc(基于标签的索引)替代iloc就行:
date1 = '31/03/2020' date2 = '31/03/2010' date1 = pd.to_datetime(date1) date2 = pd.to_datetime(date2) # 用loc按日期标签和列名定位对应值 if df_dates2.loc[date1, 'First Occurence Consolidated'] < date2: print(1) # 使用consolidated数据计算均值 else: print(2) # 使用standalone数据计算均值
注意:你的列名First Occurence Consolidated可能有拼写错误(应该是Occurrence),如果运行时提示列不存在,先检查列名正确性。
情况2:df_dates2是默认整数索引
如果你的DataFrame用的是默认整数索引,需要先找到date1对应的行位置,再用iloc定位:
date1 = '31/03/2020' date2 = '31/03/2010' date1 = pd.to_datetime(date1) date2 = pd.to_datetime(date2) # 找到目标日期对应的行索引 row_idx = df_dates2[df_dates2['date'] == date1].index[0] # 找到目标列的整数位置 col_idx = df_dates2.columns.get_loc('First Occurence Consolidated') if df_dates2.iloc[row_idx, col_idx] < date2: print(1) else: print(2)
二、实现条件式10年价格均值计算+标识列
接下来解决你的核心需求:按公司分组,过去10年如果price_consolidated无NaN值就用它,否则用price_standalone,同时新增列标注使用的数据源。
思路拆解
- 先确保时间序列有序:把
date转成datetime类型并设为索引,保证滚动计算的准确性 - 按公司分组,对每个组的历史数据做滚动统计
- 通过滚动窗口的非NaN计数判断
price_consolidated是否完整,再选择对应列计算均值 - 新增
Price source列记录使用的数据源
完整代码实现
import pandas as pd # 第一步:预处理数据,确保date是datetime类型且为索引 df['date'] = pd.to_datetime(df['date']) df = df.set_index('date').sort_index() # 定义滚动窗口参数:10年按3650天计算,min_periods=1保证数据不足时仍计算均值 window_size = 3650 min_periods = 1 # 定义分组处理函数 def process_group(group): # 计算过去10年price_consolidated的非NaN值数量 consol_non_nan_count = group['price_consolidated'].shift().rolling(window=window_size, min_periods=min_periods).count() # 判断是否完全无NaN:计数等于窗口大小则用consolidated,否则用standalone use_consolidated = consol_non_nan_count == window_size # 计算两种价格的滚动均值 mean_consol = group['price_consolidated'].shift().rolling(window=window_size, min_periods=min_periods).mean() mean_standalone = group['price_standalone'].shift().rolling(window=window_size, min_periods=min_periods).mean() # 条件选择最终均值,并新增数据源标识列 group['Price mean 10 years'] = pd.where(use_consolidated, mean_consol, mean_standalone) group['Price source'] = pd.where(use_consolidated, 'price_consolidated', 'price_standalone') return group # 应用分组逻辑到整个DataFrame df = df.groupby('Company Name', group_keys=False).apply(process_group) # 可选:恢复原索引结构(如果需要把date变回普通列) df = df.reset_index()
代码说明
shift()是为了排除当前行的价格,严格计算过去10年的均值,和你之前的代码逻辑保持一致- 当公司历史数据不足10年时,
min_periods=1会让计算继续,此时consol_non_nan_count会小于window_size,自动切换到price_standalone pd.where()是矢量化操作,比循环判断高效得多,适合处理大规模数据
额外提示
如果你说的“过去10年”是指自然年的时间范围(比如从2020-03-31往前推10年到2010-03-31),而不是固定3650天(忽略闰年差异),那滚动窗口的方式可能不够准确。这种情况下需要改用按时间范围筛选的方式计算均值,如果你需要这种逻辑,可以告诉我,我再帮你调整代码。
内容的提问来源于stack exchange,提问作者Deep Vora
相关产品推荐
相关产品推荐

