You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Pandas DataFrame中计算当前值与历史最大值的涨跌幅(不含当前行)

解决Pandas中计算当前值相对于之前所有行最大值的百分比变化问题

简洁解决方案

你需要计算的是当前值相对于截至上一行的Value列最大值的百分比变化,同时保留NaN行的空值。可以通过以下简洁代码实现:

import pandas as pd
import numpy as np

# 初始化DataFrame
df = pd.DataFrame({'Value': [1000, 1100, np.nan, 1050, 990, np.nan, 1200, np.nan, 1150, 1300]})

# 计算截至上一行的累积最大值,第一行用自身值作为参考
cum_max = df['Value'].cummax()
prev_max = cum_max.shift(1).fillna(df['Value'].iloc[0])

# 计算百分比变化,仅对非NaN行计算,NaN行保留空值
df['mdd/mru'] = np.where(
    df['Value'].notna(),
    (df['Value'] - prev_max) / prev_max,
    np.nan
).round(4)

print(df)

执行后得到的结果与你的期望完全匹配:

Value  mdd/mru
0  1000.0    0.0000
1  1100.0    0.1000
2     NaN       NaN
3  1050.0   -0.0455
4   990.0   -0.1000
5     NaN       NaN
6  1200.0    0.0909
7     NaN       NaN
8  1150.0   -0.0417
9  1300.0    0.0833

关键逻辑说明

  1. cum_max = df['Value'].cummax():先计算包含当前行的累积最大值,自动忽略NaN,确保能追踪到历史所有行的最大值。
  2. prev_max = cum_max.shift(1).fillna(df['Value'].iloc[0]):将累积最大值整体下移一行,得到截至上一行的最大值;第一行下移后为NaN,替换为自身值,保证第一行计算结果为0。
  3. np.where(...):只对Value非空的行计算百分比变化,空值行直接保留NaN,避免额外的替换操作。
  4. .round(4):将结果保留四位小数,与你的期望格式一致。

为什么之前的方法不生效

  • 直接使用df['Value'].cummax()会将当前行纳入最大值计算,导致新的最大值行结果为0,不符合需求。
  • 单纯shift(1).cummax()会因为中间的NaN导致部分行的历史最大值丢失,出现无意义的NaN结果。
  • 填充NaN为0会错误地将0纳入最大值计算,导致后续行的百分比变化结果失真。

内容的提问来源于stack exchange,提问作者rose_1

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.06 01:45:41