如何避免Matplotlib连接含缺失值的无关数据点绘制曲线
问题描述
我有某区域单日逐小时温度的多月度数据集,因硬件故障存在数据缺失,缺失时长从几小时到连续数小时不等。已用NaN值标记缺失数据,补全了单日内部的缺失时段,但未处理连续多日的缺失。需要绘制整月温度随时间变化的曲线,要求仅显示非空数据,避免Matplotlib连接无关数据点。
但在2023年10月的数据绘图时出现异常:2023/10/09左右的缺失数据被错误连接,而2023/10/21至2023/10/29的大量缺失数据却未被连接。尝试按天拆分绘制来避免连接问题,但导致图例数量与天数一致,不符合需求。当前生成异常结果的代码如下:
""" 创建并展示指定月份的温度分布曲线。 参数: month_year_data (pandas.DataFrame): 包含该月份逐小时温度数据的DataFrame。 month_name (str): 用于图表标注的月份名称。 year (int): 用于图表标注的年份。 返回: None """ # 创建单个图表 fig, ax = plt.subplots(figsize=(20, 10)) # 绘制各区域的温度分布 zones = ['远区', '中区', '近区'] colors = ['blue', 'green', 'red', 'black'] # 定义各区域颜色 for i, zone in enumerate(zones): ax.plot(month_year_data.index, month_year_data[zone], label=zone, color=colors[i], linestyle='-') # 设置坐标轴标签 ax.set_xlabel('时间') ax.set_ylabel('温度 (°C)') # 设置图表标题 ax.set_title(f'{month_name}-{year}逐小时温度变化曲线') # 旋转x轴标签以提升可读性 plt.xticks(rotation=45) # 添加图例 ax.legend()
解决方案
核心思路
将每个区域的温度数据拆分为连续非NaN的子序列,分别绘制这些子序列,确保跨缺失段的无关数据点不会被连接;同时仅在首次绘制区域数据时添加图例标签,避免图例重复。
修改后的代码
""" 创建并展示指定月份的温度分布曲线。 参数: month_year_data (pandas.DataFrame): 包含该月份逐小时温度数据的DataFrame(索引为datetime类型)。 month_name (str): 用于图表标注的月份名称。 year (int): 用于图表标注的年份。 返回: None """ import matplotlib.pyplot as plt import pandas as pd # 创建单个图表 fig, ax = plt.subplots(figsize=(20, 10)) # 定义各区域及对应颜色 zones = ['远区', '中区', '近区'] colors = ['blue', 'green', 'red', 'black'] for i, zone in enumerate(zones): # 获取当前区域非NaN的温度数据 temp_series = month_year_data[zone].dropna() if temp_series.empty: continue # 跳过无有效数据的区域 # 识别连续数据段的分界点:相邻时间间隔不为1小时则为分界 time_diff = temp_series.index.to_series().diff() breaks = time_diff != pd.Timedelta(hours=1) # 按分界点分组,得到多个连续数据子序列 data_groups = temp_series.groupby(breaks.cumsum()) # 绘制每个连续数据段,仅第一个段添加图例标签 first_segment = True for _, segment in data_groups: if first_segment: ax.plot(segment.index, segment.values, label=zone, color=colors[i], linestyle='-') first_segment = False else: ax.plot(segment.index, segment.values, color=colors[i], linestyle='-') # 设置图表元素 ax.set_xlabel('时间') ax.set_ylabel('温度 (°C)') ax.set_title(f'{year}年{month_name}逐小时温度变化曲线') plt.xticks(rotation=45) ax.legend() plt.show()
代码说明
- 数据拆分:通过判断相邻时间索引的间隔是否为1小时(符合逐小时数据的特性),将非NaN数据拆分为多个连续子序列,确保每个子序列内部无缺失。
- 图例控制:仅在绘制区域的第一个连续子序列时添加
label参数,后续子序列不添加,避免图例中出现重复条目。 - 空数据处理:添加了空数据判断,避免无有效数据的区域引发绘图错误。
内容的提问来源于stack exchange,提问作者fidjii 32
相关产品推荐
相关产品推荐

