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

Pandas计算时序数据谷底及前后峰值:解决pre_peak空值问题

解决Pandas时序数据限定谷底范围后前峰值(pre_peak)空值问题

首先,我得先理清你遇到的核心问题:你把nadir(谷底)的计算范围限定在第6列之后(也就是Q22001及以后),但计算pre_peak(谷底前的最大值)时出现了空值,这大概率是因为你混淆了谷底限定区域的局部索引和全局列索引,导致pre_peak的计算范围被错误缩小了。

先重现你的场景,用代码构造示例数据:

import pandas as pd
import numpy as np

# 构造示例DataFrame
data = [
    [4085280.0, 4114911.0, 4108089.0, 4111713.0, 4055699.0, 4076430.0, 4043219.0, 4039370.0, 4201158.0, 4243119.0, 4231823.0, 4254681.0],
    [21226.0, 21566.0, 21804.0, 22072.0, 21924.0, 23232.0, 22748.0, 22258.0, 22614.0, 22204.0, 22500.0, 22660.0],
    [96400.0, 102000.0, 98604.0, 97086.0, 96354.0, 103054.0, 97824.0, 95958.0, 115938.0, 123064.0, 120406.0, 120648.0],
    [23820.0, 24116.0, 24186.0, 23726.0, 23504.0, 23574.0, 23162.0, 23078.0, 22306.0, 22334.0, 22152.0, 22080.0],
    [7838.0, 7906.0, 7714.0, 7676.0, 7480.0, 7520.0, 7102.0, 6722.0, 8324.0, 8166.0, 8208.0, 8326.0]
]

cols = ['Q12000', 'Q22000', 'Q32000', 'Q42000', 'Q12001', 'Q22001', 'Q32001', 'Q42001', 'Q12002', 'Q22002', 'Q32002', 'Q42002']
df = pd.DataFrame(data, columns=cols)

问题根源分析

你之前的代码可能犯了这个错误:在限定区域找到nadir的局部索引(比如限定区域内的第0位)后,直接用这个局部索引去切分整行数据,导致pre_peak的计算范围变成了row.iloc[:0]——也就是空数据,自然会返回空值。

正确的逻辑应该是:

  1. 在限定区域内找到nadir及其对应的全局季度列名
  2. pre_peak是该季度之前所有时序数据的最大值(而不是限定区域内nadir之前的部分)

修正后的代码实现

下面是完整的处理函数,完美解决空值问题:

def calculate_peaks_nadir(row):
    # 定义谷底计算的起始列索引(对应Q22001,1-based的第6列)
    nadir_start_col = 'Q22001'
    nadir_start_idx = row.index.get_loc(nadir_start_col)
    
    # 1. 计算nadir(限定在Q22001及以后)
    nadir_segment = row.iloc[nadir_start_idx:]
    nadir = nadir_segment.min()
    nadir_qtr = nadir_segment.idxmin()
    
    # 2. 计算pre_peak:nadir所在季度之前的所有数据的最大值
    pre_nadir_segment = row.iloc[:row.index.get_loc(nadir_qtr)]
    if not pre_nadir_segment.empty:
        pre_peak = pre_nadir_segment.max()
        pre_peak_qtr = pre_nadir_segment.idxmax()
    else:
        # 理论上不会触发,因为nadir限定在Q22001及以后,前面必有数据
        pre_peak = np.nan
        pre_peak_qtr = None
    
    # 3. 计算post_peak:nadir所在季度之后的所有数据的最大值
    post_nadir_segment = row.iloc[row.index.get_loc(nadir_qtr)+1:]
    if not post_nadir_segment.empty:
        post_peak = post_nadir_segment.max()
        post_peak_qtr = post_nadir_segment.idxmax()
    else:
        post_peak = np.nan
        post_peak_qtr = None
    
    return pd.Series({
        'nadir': nadir,
        'nadir_qtr': nadir_qtr,
        'pre_peak': pre_peak,
        'pre_peak_qtr': pre_peak_qtr,
        'post_peak': post_peak,
        'post_peak_qtr': post_peak_qtr
    })

# 应用到每行并合并结果
result_df = df.apply(calculate_peaks_nadir, axis=1)
final_df = pd.concat([df, result_df], axis=1)

关键修正点

  • 用row.index.get_loc(nadir_qtr)获取nadir的全局列索引,确保pre_peak的计算范围是时序上真正在谷底之前的所有数据
  • 直接用列名Q22001来定义nadir的起始范围,比硬编码索引更直观,也避免列顺序变化导致的错误
  • 增加了空值判断逻辑,虽然在你的场景下不会触发,但让代码更健壮

验证第二行数据

第二行的nadir限定在Q22001及以后,最小值是22204.0(对应Q22002),pre_peak会正确计算为Q22001的23232.0,不会出现空值。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.09 13:12:53