
本文介绍在使用 matplotlib 绘制长时间跨度(如整月)温度时间序列时,如何正确处理 nan 缺失值,避免因时间断点未显式标记而导致的异常连线问题。核心方案是通过 pd.date_range 和 reindex 对齐等间隔时间索引,确保所有缺失时段被显式填充为 nan。
本文介绍在使用 matplotlib 绘制长时间跨度(如整月)温度时间序列时,如何正确处理 nan 缺失值,避免因时间断点未显式标记而导致的异常连线问题。核心方案是通过 pd.date_range 和 reindex 对齐等间隔时间索引,确保所有缺失时段被显式填充为 nan。
Matplotlib 的 ax.plot() 默认将连续非 NaN 的数据点用直线连接,而完全不关心两点之间的真实时间间隔。这意味着:即使两段有效数据相隔数天(例如 10 月 20 日 23:00 和 10 月 25 日 00:00),只要中间没有插入 NaN,Matplotlib 就会画一条跨越空白期的“飞线”——这正是你在图中观察到“2023/10/09 处被连接,而 10/21–10/29 却未连接”的根本原因:后者恰好存在未对齐的索引断层,而前者因原始数据索引不规则,意外形成了“看似连续”的序列。
✅ 正确做法是:强制构建一个完整、等频、无间隙的时间索引(如每小时一次),再将原始数据重采样(reindex)到该索引上。这样,所有真实缺失的小时都会被显式标记为 NaN,Matplotlib 自然会在这些位置断开曲线。
以下是推荐的修复代码(集成到你原有逻辑中):
import pandas as pd
import matplotlib.pyplot as plt
# 假设 month_year_data 已加载,且 index 为 DatetimeIndex
# Step 1: 构建覆盖全时段的等间隔小时索引
full_hourly_index = pd.date_range(
start=month_year_data.index.min(),
end=month_year_data.index.max(),
freq='H' # 每小时一个点
)
# Step 2: 重索引,自动用 NaN 填充缺失时间点
month_year_data_filled = month_year_data.reindex(full_hourly_index)
# Step 3: 绘图(其余部分保持不变,但使用 filled 数据)
fig, ax = plt.subplots(figsize=(20, 10))
zones = ['Far range', 'Mid range', 'Near range']
colors = ['blue', 'green', 'red']
for i, zone in enumerate(zones):
ax.plot(
month_year_data_filled.index,
month_year_data_filled[zone],
label=zone,
color=colors[i],
linestyle='-',
linewidth=1.2
)
ax.set_xlabel('Time')
ax.set_ylabel('Temperature (°C)')
ax.set_title(f'Temperature as a function of time by Hour - {month_name}-{year}')
plt.xticks(rotation=45)
ax.legend()
plt.tight_layout()
plt.show()
⚠️ 注意事项:
- 确保 month_year_data.index 是 DatetimeIndex 类型(可用 pd.to_datetime() 转换);
- 若原始数据存在重复时间戳,reindex 前建议先去重或聚合(如 .groupby(level=0).mean());
- 频率 freq='H' 可根据实际采样粒度调整(如 '30T' 表示每30分钟);
- 此方法不会插值补全数据,仅做“占位”,完全保留原始观测的真实性;
- 若内存受限(如多年每小时数据),可考虑分段处理,但务必保证每段首尾与全局索引对齐。
总结:时间序列可视化中的“意外连线”,本质是索引不规范导致的视觉误导。通过显式构造等频时间轴并严格 reindex,我们让缺失值真正“可见”,从而赋予 Matplotlib 正确断线的依据——这不是绕过问题,而是以数据工程的方式,让可视化忠实地反映数据的本质结构。











