如何为Pandas多索引DataFrame添加‘历史最高值出现时间’列?
问题:为Pandas多索引DataFrame添加“最后一次高于当前值的时间”列
首先创建的多索引DataFrame代码如下:
import pandas as pd import numpy as np names = ['Alice', 'Bob', 'Charlie', 'David', 'Emily'] years = [2019, 2020, 2021, 2022, 2023] months = ['Jan', 'Feb', 'Mar', 'Apr', 'May'] data = np.random.randint(1, 100, size=(5, 25)) df = pd.DataFrame(data, index=names, columns=pd.MultiIndex.from_product([years, months]))
该DataFrame以人名作为行索引,日期(年+月)作为多级列索引,值为随机整数。需求是在DataFrame末尾添加一列highest_since,标识最后一列(2023年5月)对应值的历史上最后一次高于该值的时间。
用户尝试的代码如下,但运行报错:
cols=df.columns.tolist() def highest_since(row): z=-1 if df[cols[-1]]>df[cols[z-1]]==True: z=z-1 else: return df[cols[z]] df['highest_since']=df[cols[-1]].apply(highest_since)
错误分析
- 函数
highest_since错误使用全局df而非传入的row,无法处理单行数据 - 未实现反向循环遍历历史列的逻辑,仅做单次判断就返回
- 条件判断
df[cols[-1]]>df[cols[z-1]]==True写法错误,逻辑不符合“找最后一次高于当前值”的需求
解决方案
方法1:逐行反向遍历(直观易理解)
遍历每一行,从倒数第二列开始反向查找第一个值大于最后一列值的列,返回该列的多级索引(年+月):
# 获取所有历史列(排除最后一列) history_cols = df.columns[:-1] # 最后一列(当前值列) current_col = df.columns[-1] def find_last_higher(row): current_val = row[current_col] # 反向遍历历史列,找到第一个值大于当前值的列 for col in reversed(history_cols): if row[col] > current_val: return col return None # 历史中无更高值时返回None # 应用函数到每一行 df['highest_since'] = df.apply(find_last_higher, axis=1)
方法2:向量化处理(高效,适合大数据集)
利用Pandas向量化操作避免逐行循环,提升运行效率:
import numpy as np # 获取最后一列的当前值 current_vals = df.iloc[:, -1] # 生成历史列与当前值的比较掩码(True表示该列值大于当前值) higher_mask = df.iloc[:, :-1].values > current_vals.values[:, np.newaxis] # 从后往前找第一个True的索引 last_higher_indices = higher_mask.shape[1] - 1 - np.argmax(higher_mask[:, ::-1], axis=1) # 标记无更高值的行 last_higher_indices[~higher_mask.any(axis=1)] = -1 # 根据索引匹配对应的列索引 df['highest_since'] = [df.columns[i] if i != -1 else None for i in last_higher_indices]
运行后,highest_since列会显示每个人对应的“最后一次值高于2023年5月值”的年份和月份,无符合条件的记录则显示None。
内容的提问来源于stack exchange,提问作者Robert Tuttle
相关产品推荐
相关产品推荐

