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

用Pandas向量化方法查找列中首个后续小于当前值的索引

高效解决Pandas中"下一个更小元素索引"及区间最大值问题

一、计算F(Val):每行之后首个小于当前值的索引

针对大数据集,逐行循环的O(n²)复杂度会导致严重性能问题,单调栈是线性时间O(n)的最优解法,完全避免冗余计算:

实现代码

import numpy as np
import pandas as pd

df = pd.DataFrame({'Val': [1, 2, 3, 4, 0, 1, -1, -2, -3]}, index=np.arange(0,9))

# 初始化单调栈与结果数组
stack = []
f_val = np.full(len(df), np.nan)

# 从后往前遍历,维护单调递增栈
for i in reversed(range(len(df))):
    # 弹出栈中所有不小于当前值的元素,保证栈顶是下一个更小元素
    while stack and df['Val'].iloc[stack[-1]] >= df['Val'].iloc[i]:
        stack.pop()
    # 栈不为空时,栈顶即为目标索引
    if stack:
        f_val[i] = stack[-1]
    stack.append(i)

df['F(Val)'] = f_val

核心逻辑

单调栈始终维护一个对应值单调递增的索引序列:

  • 从后往前遍历,每次清理栈中不小于当前值的元素,剩余栈顶就是第一个比当前值小的元素索引
  • 每个元素仅入栈、出栈各一次,时间复杂度严格O(n),处理百万级数据也能保持高效

二、计算G(Val):当前索引到F(Val)区间内的最大值

利用F(Val)的单调性质,我们可以通过反向递推实现O(n)时间的高效计算,无需重复遍历区间:

实现代码

g_val = np.full(len(df), np.nan)

# 从倒数第二行反向递推
for i in reversed(range(len(df)-1)):
    # 若下一个更小元素就是相邻行,区间最大值就是当前值
    if df['F(Val)'].iloc[i] == i+1:
        g_val[i] = df['Val'].iloc[i]
    else:
        # 否则区间最大值为当前值与下一行G(Val)的较大值
        g_val[i] = max(df['Val'].iloc[i], g_val[i+1])

df['G(Val)'] = g_val

核心逻辑

观察区间规律:[i, F(Val)]的最大值,等于当前值Val[i]和[i+1, F(Val)]的最大值(即G(Val)[i+1])中的较大者,而F(Val)的单调性保证了[i+1, F(Val)]的最大值已被提前计算。


最终结果

运行代码后,DataFrame将生成期望的结果列:

IndexValF(Val)G(Val)
014.04.0
124.04.0
234.04.0
344.04.0
406.01.0
516.01.0
6-17.0-1.0
7-28.0-2.0
8-3NaNNaN

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 23:10:56