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

Pandas大数据集优化:获取当前日期前最大日期的分数极值

Pandas 高效实现「获取当前日期前最大日期的Score极值」需求

我需要在Pandas DataFrame中,为每条数据找到当前testdate之前的最大日期,再获取该日期对应的score最大值与最小值,并将结果作为新列添加至DataFrame。现有代码可实现需求,但因数据集规模庞大,运行效率偏低,特寻求更高效的实现方案。

现有实现代码

版本1:分函数实现

def findMax(x):
    import numpy as np
    larger = frame.testdate[frame.testdate < x]
    if len(larger) != 0:
        return max(larger)
    else:
        return np.nan
    
def scorerange(row):
        x=frame.loc[frame['testdate'] == row.PriorDate]
        return x.score.max(),x.score.min()

import pandas as pd
data = {'testdate' : ['2022-04-01', '2022-04-01', '2022-03-29', '2022-03-29','2022-03-27', '2022-03-27'],
    'student' : ['Joe', 'Mary', 'Joe', 'Mary', 'Joe', 'Mary'],
    'score' : [35, 45, 83,79,40,80]}
frame = pd.DataFrame(data)
frame.testdate=pd.to_datetime(frame.testdate)
frame['PriorDate']=frame.testdate.apply(findMax)
frame['resultmax'],frame['resultmin'] = zip(*frame.apply(scorerange, axis=1))
frame

版本2:单函数实现

def findall(x):
    import numpy as np
    larger = frame.testdate[frame.testdate < x]
    if len(larger) != 0:
        x=frame.loc[frame['testdate'] == max(larger)]
        return max(larger),x.score.max(),x.score.min()
    else:
        return np.nan,np.nan,np.nan

frame['PriorDate'],frame['resultmax'],frame['resultmin'] = zip(*frame.testdate.apply(findall))

现有方案的效率问题

现有代码依赖apply逐行遍历,本质是Python层面的循环操作,时间复杂度为O(n²)——每次调用函数都要全表筛选日期,在大数据集下会导致严重的性能瓶颈。

高效实现方案

核心思路是通过预处理聚合+向量式映射替代逐行计算,利用Pandas内置的优化操作避免循环开销,时间复杂度降至O(n log n)(主要来自排序步骤)。

具体步骤与代码

  1. 按日期聚合Score极值:先计算每个日期对应的score最大、最小值,生成日期-极值映射表
  2. 生成日期前序映射:对唯一日期排序后,通过shift快速获取每个日期的前序最大日期
  3. 关联回原表:将日期映射与极值表合并,最终关联到原DataFrame
import pandas as pd
import numpy as np

# 1. 加载并预处理数据
data = {
    'testdate': ['2022-04-01', '2022-04-01', '2022-03-29', '2022-03-29','2022-03-27', '2022-03-27'],
    'student': ['Joe', 'Mary', 'Joe', 'Mary', 'Joe', 'Mary'],
    'score': [35, 45, 83,79,40,80]
}
frame = pd.DataFrame(data)
frame['testdate'] = pd.to_datetime(frame['testdate'])

# 2. 按日期聚合score的最大、最小值
date_score_stats = frame.groupby('testdate')['score'].agg(['max', 'min']).reset_index()
date_score_stats.columns = ['testdate', 'score_max', 'score_min']

# 3. 生成每个日期的前序最大日期映射
unique_dates = date_score_stats['testdate'].sort_values().reset_index(drop=True)
date_mapping = pd.DataFrame({
    'testdate': unique_dates,
    'PriorDate': unique_dates.shift(1)  # 排序后shift(1)即为前一个最大日期
})

# 4. 合并映射表并关联回原DataFrame
date_prior_stats = pd.merge(
    date_mapping,
    date_score_stats,
    left_on='PriorDate',
    right_on='testdate',
    how='left'
).drop(columns='testdate_y').rename(columns={
    'testdate_x': 'testdate',
    'max': 'resultmax',
    'min': 'resultmin'
})

frame = pd.merge(frame, date_prior_stats, on='testdate', how='left')

方案优势

  • 全部采用Pandas内置的向量化操作,避免Python循环的性能损耗
  • 聚合与映射仅需几次全表扫描,而非逐行的重复筛选
  • 适用于百万级甚至更大规模的数据集,性能提升显著

内容的提问来源于stack exchange,提问作者Stumbling Through Data Science

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.18 08:11:37