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

对无数据列的DataFrame执行rolling操作时的异常行为

Pandas rolling 聚合操作丢失time列的异常问题

先看正常场景的代码,能生成符合预期的结果:

import pandas as pd
import numpy as np

data = pd.DataFrame({'time': pd.date_range('2024-01-01 00:00',
                                           '2024-01-02 00:00',
                                           freq='1H'),
                    'data' : np.random.rand(25)})

# 正常返回包含time和data列的结果
data.rolling(window='3H', on='time').max()

但当移除唯一的数值列data后,执行相同的rolling+max操作:

# 仅保留time列的DataFrame执行rolling操作
data.drop(columns=['data']).rolling('3H', on='time').max()

程序既不报错也不提示警告,却返回一个只有索引、没有任何列的空DataFrame,导致后续依赖time列的处理流程直接失败。按预期,即便这个操作没有实际聚合意义,也应该返回输入的原DataFrame,而非丢失唯一的time列。

问题原因

Pandas的rolling聚合方法(比如max()、mean())只会对数值类型的列执行计算,而time列是datetime类型,不属于聚合目标范围。当DataFrame里没有数值列时,聚合操作找不到可处理的列,最终就返回了无列的空DataFrame。同时,on参数指定的time列只会作为rolling窗口的分组依据,不会自动被保留到结果中。

解决方案

可以通过提前判断或自定义逻辑来避免这个问题:

  • 方案1:提前检查是否有数值列
    在执行rolling操作前,先判断DataFrame里是否存在数值类型的列,没有则直接返回原数据:
    df = data.drop(columns=['data'])
    if np.any(df.dtypes == 'float64') or np.any(df.dtypes == 'int64'):
        result = df.rolling('3H', on='time').max()
    else:
        result = df.copy()
    
  • 方案2:强制保留time列
    如果需要保留time列,哪怕聚合操作无意义,可以手动将time列转为数值类型(比如时间戳)参与聚合,之后再转回来:
    df = data.drop(columns=['data']).copy()
    df['time_ts'] = df['time'].astype('int64')
    result = df.rolling('3H', on='time').max().drop(columns=['time_ts'])
    # 恢复原time列
    result['time'] = df['time']
    
  • 方案3:自定义聚合函数
    使用agg方法,指定对time列做恒等映射,确保列被保留:
    df = data.drop(columns=['data'])
    result = df.rolling('3H', on='time').agg({'time': lambda x: x.iloc[-1]})
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 00:07:42