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

如何统计Python DataFrame当前值在前30条前序行内的出现次数

统计DataFrame每行id在最近30条历史记录中的出现次数

原代码核心问题

  • 取值逻辑错误:val = df_current['id'].index 实际取的是行索引而非id列的对应值
  • 循环中直接修改原始df_current变量,第一次循环后原始数据就被截断,后续所有计算都会出错
  • 历史数据切片逻辑错误,并不是取df_previous[i:],而是需要取df_previous末尾的若干行来补齐不足30条的前序样本缺口
  • 仅统计了id是否存在,没有统计出现次数,不符合需求

实现前提

两个DataFrame均已按时间升序排列,df_previous存储早于df_current的历史数据,行顺序严格对应时间先后。

正确实现代码

方案1:逐行遍历实现(逻辑直观,适合百级/千级小数据量)

import pandas as pd
WINDOW_SIZE = 30
# 给当前df新增列存储统计结果
df_current['id_prev_30_count'] = 0
prev_len = len(df_previous)

for idx in range(len(df_current)):
    # 取当前行的id值
    current_id = df_current.iloc[idx]['id']
    # 计算当前行能从当前df拿到的前序历史行数
    current_available = idx
    fill_num = WINDOW_SIZE - current_available
    
    # 拼接得到刚好30条的前序历史窗口
    if fill_num > 0:
        # 需要从更早的历史df补数据,取df_previous最后fill_num行 + 当前df前idx行
        fill_part = df_previous.tail(fill_num)
        history_window = pd.concat([fill_part, df_current.head(idx)])
    else:
        # 前序行足够,直接取当前行往前数30条
        history_window = df_current.iloc[idx-WINDOW_SIZE : idx]
    
    # 统计当前id在历史窗口中的出现次数
    count = (history_window['id'] == current_id).sum()
    df_current.loc[df_current.index[idx], 'id_prev_30_count'] = count

方案2:向量化滑动窗口实现(效率更高,适合万级以上大数据量)

不用逐行遍历,利用pandas内置的rolling滑动窗口能力实现,性能提升数十倍:

import pandas as pd
WINDOW_SIZE = 30
# 按时间顺序拼接历史和当前数据,ignore_index重置行索引保证时序正确
full_df = pd.concat([df_previous, df_current], ignore_index=True)

# 滑动窗口计算:窗口大小设为31,closed='left'表示仅统计当前行之前的30条数据
full_df['id_prev_30_count'] = full_df['id'].rolling(window=WINDOW_SIZE+1, closed='left').apply(
    lambda x: (x == x.iloc[-1]).sum(),
    include_groups=False
).fillna(0) # 前30行无足够历史时填充0,可根据需求调整

# 提取当前df对应的结果,写回原df_current
df_current['id_prev_30_count'] = full_df['id_prev_30_count'].iloc[len(df_previous):].values

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.04 10:24:02