Matplotlib图表区域事件驱动型背景着色教程

DDD
发布: 2025-10-04 12:54:29
原创
709人浏览过

Matplotlib图表区域事件驱动型背景着色教程

本教程详细介绍了如何在Matplotlib图表中根据特定事件数据为图表的不同区域进行背景着色。通过识别数据系列中的事件发生点,并利用axvspan函数,我们可以为事件发生前、发生中和发生后的区域应用不同的颜色,从而增强数据可视化效果,突出关键时间段。教程提供了详细的代码示例和注意事项,帮助用户实现精确的区域着色。

引言

在数据分析和可视化中,我们经常需要突出图表中的特定时间段或数据区域,以标记事件、异常值或重要阶段。matplotlib提供了强大的绘图功能,其中axvspan函数是实现垂直区域着色的关键工具。本教程将指导您如何根据一个独立的事件序列(例如,一个表示事件发生与否的二进制序列)来动态地为图表的不同部分着色,特别地,我们将实现事件发生前、发生中和发生后三个阶段的不同颜色标记。

核心概念:axvspan函数

matplotlib.axes.Axes.axvspan(xmin, xmax, ymin=0, ymax=1, **kwargs) 函数用于在坐标轴上绘制一个垂直的矩形区域。

  • xmin, xmax: 定义了矩形区域的水平范围。
  • ymin, ymax: 定义了矩形区域的垂直范围,默认是0到1,表示覆盖整个y轴范围。
  • facecolor: 矩形区域的填充颜色。
  • alpha: 矩形区域的透明度,值介于0(完全透明)和1(完全不透明)之间。

通过多次调用axvspan并指定不同的xmin、xmax和facecolor,我们可以创建多个自定义着色区域。

准备数据

首先,我们需要模拟一些数据,包括主数据系列和用于触发着色事件的事件序列。事件序列通常是一个二进制值,例如0表示无事件,1表示事件发生。

import numpy as np
import matplotlib.pyplot as plt
import pandas as pd

# 设置随机种子以便结果可复现
np.random.seed(42)

# 生成事件数据,初始为0
data_length = 56
event = pd.DataFrame(np.zeros(data_length, dtype=int), columns=['event_status'])

# 模拟事件发生
# 事件1:从索引10到13(即[10:14])
event.iloc[10:14, 0] = 1
# 事件2:从索引24到35(即[24:36])
event.iloc[24:36, 0] = 1

# 生成主图表数据
data_series_1 = pd.DataFrame(np.random.randint(200, 300, size=(data_length, 1)), columns=['Series1'])
data_series_2 = pd.DataFrame(np.random.randint(0, 3, size=(data_length, 1)), columns=['Series2'])
data_series_3 = pd.DataFrame(np.random.randint(300, 400, size=(data_length, 1)), columns=['Series3'])
data_series_4 = pd.DataFrame(np.random.randint(0, 5, size=(data_length, 1)), columns=['Series4'])
登录后复制

识别事件周期

为了实现精确着色,我们需要从事件序列中识别出所有连续的事件发生周期(即event值为1的连续区间)。

def find_event_periods(event_series):
    """
    识别事件序列中值为1的连续周期。
    返回一个列表,每个元素是一个元组 (start_index, end_index),
    其中end_index是该周期的结束索引(不包含)。
    """
    event_periods = []
    in_event = False
    start_idx = -1

    for i in range(len(event_series)):
        if event_series.iloc[i] == 1 and not in_event:
            start_idx = i
            in_event = True
        elif event_series.iloc[i] == 0 and in_event:
            event_periods.append((start_idx, i))
            in_event = False

    # 处理事件持续到序列末尾的情况
    if in_event:
        event_periods.append((start_idx, len(event_series)))

    return event_periods

event_periods = find_event_periods(event['event_status'])
print(f"识别到的事件周期: {event_periods}")
登录后复制

输出示例:识别到的事件周期: [(10, 14), (24, 36)]

爱图表
爱图表

AI驱动的智能化图表创作平台

爱图表99
查看详情 爱图表

实现区域着色逻辑

现在,我们将根据识别到的事件周期,为每个周期定义三个着色区域:

  1. 事件前区域 (Pre-event): 事件开始前一个索引到事件开始的区域。
  2. 事件中区域 (During-event): 事件发生期间的区域。
  3. 事件后区域 (Post-event): 事件结束后两个索引的区域。

我们将定义这些区域的颜色和透明度。

# 定义着色方案
color_pre_event = 'skyblue'  # 事件前区域颜色
color_during_event = 'lightcoral' # 事件中区域颜色
color_post_event = 'lightgreen' # 事件后区域颜色
alpha_level = 0.2 # 透明度
登录后复制

完整代码示例

以下是整合了数据生成、事件识别和区域着色逻辑的完整Matplotlib绘图代码。它将使用原始问题中定义的双轴子图结构。

import numpy as np
import matplotlib.pyplot as plt
import pandas as pd

# --- 1. 数据准备 ---
np.random.seed(42) # 确保结果可复现

data_length = 56
event = pd.DataFrame(np.zeros(data_length, dtype=int), columns=['event_status'])
event.iloc[10:14, 0] = 1 # 事件1
event.iloc[24:36, 0] = 1 # 事件2

# 主图表数据
data_series_1 = pd.DataFrame(np.random.randint(200, 300, size=(data_length, 1)), columns=['Series1'])
data_series_2 = pd.DataFrame(np.random.randint(0, 3, size=(data_length, 1)), columns=['Series2'])
data_series_3 = pd.DataFrame(np.random.randint(300, 400, size=(data_length, 1)), columns=['Series3'])
data_series_4 = pd.DataFrame(np.random.randint(0, 5, size=(data_length, 1)), columns=['Series4'])

# --- 2. 事件周期识别函数 ---
def find_event_periods(event_series):
    event_periods = []
    in_event = False
    start_idx = -1

    for i in range(len(event_series)):
        if event_series.iloc[i] == 1 and not in_event:
            start_idx = i
            in_event = True
        elif event_series.iloc[i] == 0 and in_event:
            event_periods.append((start_idx, i))
            in_event = False

    if in_event:
        event_periods.append((start_idx, len(event_series)))

    return event_periods

event_periods = find_event_periods(event['event_status'])

# --- 3. 定义着色方案 ---
color_pre_event = 'blue'      # 事件前区域颜色
color_during_event = 'red'    # 事件中区域颜色
color_post_event = 'green'    # 事件后区域颜色
alpha_level = 0.2             # 透明度

# --- 4. 绘图部分 ---
plt.figure(figsize=(18, 8)) # 调整图表大小以适应内容和布局

# 第一个子图 (2行2列的第1个)
ax1 = plt.subplot(1, 2, 1) # 调整为1行2列,便于展示
ax2 = ax1.twinx() # 创建第二个y轴

# 绘制主数据系列
ax1.plot(data_series_1, label='Series 1', color='g')
ax1.plot(data_series_2, label='Series 2', color='r')
ax2.plot(event, label='Event Status', color='k', linestyle='--', linewidth=1) # 事件状态曲线

# 应用区域着色
for start, end in event_periods:
    # 事件前区域: 从 max(0, start-1) 到 start
    pre_event_xmin = max(0, start - 1)
    pre_event_xmax = start
    if pre_event_xmin < pre_event_xmax: # 确保区域有效
        ax1.axvspan(pre_event_xmin, pre_event_xmax, facecolor=color_pre_event, alpha=alpha_level, label='Pre-Event' if start == event_periods[0][0] else "")

    # 事件中区域: 从 start 到 end
    ax1.axvspan(start, end, facecolor=color_during_event, alpha=alpha_level, label='During-Event' if start == event_periods[0][0] else "")

    # 事件后区域: 从 end 到 min(data_length, end+2)
    post_event_xmin = end
    post_event_xmax = min(data_length, end + 2)
    if post_event_xmin < post_event_xmax: # 确保区域有效
        ax1.axvspan(post_event_xmin, post_event_xmax, facecolor=color_post_event, alpha=alpha_level, label='Post-Event' if start == event_periods[0][0] else "")

# 设置标签和标题
ax1.set_ylabel('Value (m)', fontsize=12)
ax2.set_ylabel('Event Status (t)', color='k', fontsize=12)
ax1.set_title('图表 0: 事件驱动背景着色示例', fontsize=14)
ax1.tick_params(axis='y', labelsize=10)
ax1.tick_params(axis='x', labelsize=10)
ax2.tick_params(axis='y', labelsize=10)

# 合并图例,避免重复标签
lines, labels = ax1.get_legend_handles_labels()
lines2, labels2 = ax2.get_legend_handles_labels()
# 过滤掉axvspan的重复标签,只保留第一次出现的
unique_labels = {}
for line, label in zip(lines + lines2, labels + labels2):
    if label not in unique_labels:
        unique_labels[label] = line
ax1.legend(unique_labels.values(), unique_labels.keys(), loc='upper left', prop={'size': 10})


# 第二个子图 (2行2列的第2个) - 结构与第一个类似,但使用不同的数据
ax3 = plt.subplot(1, 2, 2)
ax4 = ax3.twinx()

ax3.plot(data_series_3, label='Series 3', color='purple')
ax3.plot(data_series_4, label='Series 4', color='orange')
ax4.plot(event, label='Event Status', color='k', linestyle='--', linewidth=1)

# 应用区域着色 (与第一个子图逻辑相同)
for start, end in event_periods:
    pre_event_xmin = max(0, start - 1)
    pre_event_xmax = start
    if pre_event_xmin < pre_event_xmax:
        ax3.axvspan(pre_event_xmin, pre_event_xmax, facecolor=color_pre_event, alpha=alpha_level)

    ax3.axvspan(start, end, facecolor=color_during_event, alpha=alpha_level)

    post_event_xmin = end
    post_event_xmax = min(data_length, end + 2)
    if post_event_xmin < post_event_xmax:
        ax3.axvspan(post_event_xmin, post_event_xmax, facecolor=color_post_event, alpha=alpha_level)

ax3.set_ylabel('Value (m)', fontsize=12)
ax4.set_ylabel('Event Status (t)', color='k', fontsize=12)
ax3.set_title('图表 1: 事件驱动背景着色示例', fontsize=14)
ax3.tick_params(axis='y', labelsize=10)
ax3.tick_params(axis='x', labelsize=10)
ax4.tick_params(axis='y', labelsize=10)

# 合并图例
lines, labels = ax3.get_legend_handles_labels()
lines2, labels2 = ax4.get_legend_handles_labels()
unique_labels = {}
for line, label in zip(lines + lines2, labels + labels2):
    if label not in unique_labels:
        unique_labels[label] = line
ax3.legend(unique_labels.values(), unique_labels.keys(), loc='upper left', prop={'size': 10})

plt.tight_layout() # 自动调整子图参数,使之填充整个图像区域
plt.show()
登录后复制

代码解析与注意事项

  1. 数据生成与事件定义:
    • event DataFrame用于存储事件状态,其中0表示无事件,1表示事件发生。
    • iloc用于精确设置事件发生的区间。
  2. find_event_periods函数:
    • 此函数通过遍历event_series来识别连续的1值块。它返回一个元组列表,每个元组(start, end)表示一个事件周期的起始和结束索引(end是排他性的)。
    • 这种方法比简单地查找1的索引更健壮,因为它能正确处理连续的事件块。
  3. 着色方案定义:
    • color_pre_event, color_during_event, color_post_event定义了三个阶段的颜色。
    • alpha_level控制着色区域的透明度,通常设置为0.1到0.3之间,以便背景色不遮盖主要数据线。
  4. axvspan调用:
    • 对于每个识别到的事件周期(start, end),我们计算并调用三次axvspan:
      • 事件前: xmin为max(0, start - 1),xmax为start。max(0, ...)确保区域不会超出图表左边界。
      • 事件中: xmin为start,xmax为end。
      • 事件后: xmin为end,xmax为`min(data_length, end +

以上就是Matplotlib图表区域事件驱动型背景着色教程的详细内容,更多请关注php中文网其它相关文章!

驱动精灵
驱动精灵

驱动精灵基于驱动之家十余年的专业数据积累,驱动支持度高,已经为数亿用户解决了各种电脑驱动问题、系统故障,是目前有效的驱动软件,有需要的小伙伴快来保存下载体验吧!

下载
来源:php中文网
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
最新问题
开源免费商场系统广告
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板
关于我们 免责申明 意见反馈 讲师合作 广告合作 最新更新 English
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送
PHP中文网APP
随时随地碎片化学习
PHP中文网抖音号
发现有趣的

Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号