Python中pandas处理时间列缺失数据,如何优化填充代码以提高效率?

DAT_DAY DAT_MONTH DATE_YEAR UTC_HOUR UTC_MIN UTC_MIN_SEC UTC_SEC
0 4.0 NaN NaN 13.0 NaN NaN NaN
1 NaN 12.0 17.0 NaN NaN NaN NaN
2 NaN NaN NaN NaN NaN NaN NaN
3 NaN NaN NaN NaN 40.0 0:40:27 27.0
4 4.0 NaN NaN 13.0 NaN NaN NaN


数据上为递增且连续,例如 0 序号数据应为:4、12、17、13、40、0:40:24、24
主要是处理时、分、秒数据,求给个方法或思路
Python中pandas处理时间列缺失数据,如何优化填充代码以提高效率?


3 回复
import pandas as pd
import numpy as np

# 创建示例数据
date_rng = pd.date_range('2023-01-01', '2023-01-10', freq='D')
df = pd.DataFrame(date_rng, columns=['timestamp'])
df['value'] = np.random.randn(len(date_rng))

# 随机删除30%的数据模拟缺失
mask = np.random.rand(len(df)) > 0.7
df.loc[mask, 'value'] = np.nan

# 优化后的填充方案
def optimize_time_fill(df, time_col='timestamp', value_col='value'):
    """
    高效处理时间序列缺失值的完整方案
    """
    # 1. 确保时间列格式正确
    df[time_col] = pd.to_datetime(df[time_col])
    df = df.sort_values(time_col).reset_index(drop=True)
    
    # 2. 设置时间索引(关键优化)
    df_indexed = df.set_index(time_col)
    
    # 3. 多种填充策略组合
    # 前向填充(优先使用,保持时间连续性)
    df_filled = df_indexed.ffill()
    
    # 后向填充补充前向填充的不足
    df_filled = df_filled.bfill()
    
    # 4. 对于连续缺失使用插值(线性插值适合时间序列)
    df_filled[value_col] = df_filled[value_col].interpolate(
        method='linear',  # 线性插值
        limit_direction='both'  # 双向插值
    )
    
    # 5. 返回原始格式
    result = df_filled.reset_index()
    return result

# 执行优化填充
df_filled = optimize_time_fill(df)

# 验证结果
print("原始数据缺失数量:", df['value'].isna().sum())
print("填充后缺失数量:", df_filled['value'].isna().sum())
print("\n填充后的数据:")
print(df_filled.head(10))

核心优化点:

  1. 设置时间索引set_index(time_col) 是最大优化,pandas对DatetimeIndex有专门优化
  2. 向量化操作:使用 ffill()bfill()interpolate() 等向量化方法,避免循环
  3. 方法链调用:减少中间变量创建,提高内存效率
  4. 排序数据:确保时间顺序正确,这对插值至关重要

如果数据量极大(百万级以上):

# 使用更高效的重采样方法
df_indexed = df.set_index('timestamp')
df_resampled = df_indexed.resample('D').mean()  # 按天重采样
df_filled = df_resampled.interpolate(method='time')  # 基于时间的插值

一句话总结:用时间索引+向量化操作替代循环。


先把 index 转换成 datetimeindex,然后从 index 中提取相关信息

连续且递增?每一条都递增一秒?那就太简单了

首先手动找出第 0 号数据,就比如你写的那个,这一步要手动找出来

<br>dt = pd.datetime(2017,12,4,13,40,24)<br>ser = pd.Series([dt]*10000)<br>dt2 = pd.Series(map(lambda x:pd.Timedelta(x,unit="s"),ser.index.values)) + ser<br>dt2.apply(lambda x:(x.day,x.month,x.year,x.hour))<br>

最后一步可以不要,只是用于格式化输出的

回到顶部