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处理时间列缺失数据,如何优化填充代码以提高效率?
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))
核心优化点:
- 设置时间索引:
set_index(time_col)是最大优化,pandas对DatetimeIndex有专门优化 - 向量化操作:使用
ffill()、bfill()、interpolate()等向量化方法,避免循环 - 方法链调用:减少中间变量创建,提高内存效率
- 排序数据:确保时间顺序正确,这对插值至关重要
如果数据量极大(百万级以上):
# 使用更高效的重采样方法
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>
最后一步可以不要,只是用于格式化输出的

