You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Plotly绘制眼动追踪数据并添加填充色随事件变化的矩形

眼动追踪数据可视化问题解决

问题背景

我有一个眼动追踪数据集,包含四列:

  • t:时间戳的numpy数组
  • x、y:凝视点的像素坐标
  • e:取值为{0,1,2,3,4,5}的数组,标记每个样本对应的凝视事件(如注视、扫视等)

需求是绘制x、y随时间变化的曲线,并添加填充色随e值变化的矩形区域。

示例数据

import numpy as np

t = np.arange(30)
x = np.array([125.9529, 124.6142, 125.0569, 125.3117, 126.7498, 127.035,125.4822, 125.6249, 126.9371, 127.6047, 129.031 , 128.2419, 121.521 , 114.7071, 109.4141, 100.5057,  94.9606,  95.2231, 95.9032,  96.4991, 101.2602, 103.9582, 108.2527, 108.8801, 110.3254, 112.8205, 113.0079, 113.3547, 113.0962, 113.2508])
y = np.array([31.218 , 31.236 , 31.147 , 31.2614, 30.806 , 30.8423, 31.727, 32.2256, 32.0504, 32.7774, 34.7089, 37.0671, 46.309 , 55.9716, 62.4481, 68.0248, 75.4912, 79.0622, 81.2176, 83.191 , 83.7656, 84.6713, 83.9343, 82.4546, 81.1652, 80.7981, 80.2136, 80.7405, 80.4398, 80.0738])
e = np.array([1., 1., 1., 1., 1., 1., 1., 1., 1., 2., 2., 2., 2., 2., 2., 2., 2., 2., 2., 2., 3., 3., 3., 3., 3., 3., 4., 4., 4., 4.])

尝试代码及报错

import plotly.graph_objects as go
from plotly.subplots import make_subplots

fig = make_subplots()
fig.add_trace(ply.graph_objects.Line(x=t, y=x, name="X"),
              secondary_y=False, row=1, col=1)
fig.add_trace(ply.graph_objects.Line(x=t, y=y, name="Y"),
              secondary_y=False, row=1, col=1)
fig.add_shape(type="rect",
              x0=t[0], y0=0, x1=t[-1], y1=0.05 * np.max([x, y]),
              line=dict(color="black", width=2),
              fillcolor=e)

报错信息:

ValueError: Invalid value of type 'numpy.ndarray' received for the 'fillcolor' property of layout.shape


问题分析与解决

报错原因是add_shape的fillcolor仅接受单一颜色值,无法直接传入数组。要实现不同e值对应不同颜色的矩形区域,需先将e的连续相同值分组,为每组单独添加矩形。

完整代码实现

import numpy as np
import plotly.graph_objects as go
from plotly.subplots import make_subplots

# 示例数据
t = np.arange(30)
x = np.array([125.9529, 124.6142, 125.0569, 125.3117, 126.7498, 127.035,125.4822, 125.6249, 126.9371, 127.6047, 129.031 , 128.2419, 121.521 , 114.7071, 109.4141, 100.5057,  94.9606,  95.2231, 95.9032,  96.4991, 101.2602, 103.9582, 108.2527, 108.8801, 110.3254, 112.8205, 113.0079, 113.3547, 113.0962, 113.2508])
y = np.array([31.218 , 31.236 , 31.147 , 31.2614, 30.806 , 30.8423, 31.727, 32.2256, 32.0504, 32.7774, 34.7089, 37.0671, 46.309 , 55.9716, 62.4481, 68.0248, 75.4912, 79.0622, 81.2176, 83.191 , 83.7656, 84.6713, 83.9343, 82.4546, 81.1652, 80.7981, 80.2136, 80.7405, 80.4398, 80.0738])
e = np.array([1., 1., 1., 1., 1., 1., 1., 1., 1., 2., 2., 2., 2., 2., 2., 2., 2., 2., 2., 2., 3., 3., 3., 3., 3., 3., 4., 4., 4., 4.])

# 定义e值对应的颜色映射
color_map = {
    1: "#FF9999",
    2: "#99FF99",
    3: "#9999FF",
    4: "#FFFF99",
    0: "#FFCC99",
    5: "#CC99FF"
}

# 找出e值变化的索引,用于分组
change_indices = np.where(np.diff(e) != 0)[0] + 1
# 分割成连续相同e值的区间
segments = np.split(t, change_indices)
e_values = np.split(e, change_indices)

# 创建子图
fig = make_subplots()

# 添加x、y曲线
fig.add_trace(go.Scatter(x=t, y=x, name="X坐标"), row=1, col=1)
fig.add_trace(go.Scatter(x=t, y=y, name="Y坐标"), row=1, col=1)

# 计算矩形区域的y轴范围
y_max = 0.05 * np.max([x, y])

# 为每个区间添加矩形
for seg, ev in zip(segments, e_values):
    # 取当前区间的时间起止点
    x0 = seg[0]
    x1 = seg[-1]
    # 取当前区间对应的e值
    event_type = ev[0]
    # 添加矩形
    fig.add_shape(
        type="rect",
        x0=x0, y0=0,
        x1=x1, y1=y_max,
        fillcolor=color_map[event_type],
        opacity=0.3,  # 设置透明度避免遮挡曲线
        line=dict(width=0)  # 隐藏矩形边框
    )

# 更新布局
fig.update_layout(
    title="眼动追踪坐标随时间变化及事件标记",
    xaxis_title="时间戳",
    yaxis_title="像素坐标",
    showlegend=True
)

fig.show()

关键说明

  1. 分组连续事件:通过np.diff找出e值变化的位置,将时间戳和事件分割成连续相同事件的区间。
  2. 颜色映射:为每个e值定义对应的填充色,方便区分不同凝视事件。
  3. 逐个添加矩形:遍历每个事件区间,为每个区间添加独立的矩形,设置对应填充色和透明度,避免遮挡上方的坐标曲线。
  4. 修复原代码错误:原代码中ply是笔误,应改为go;同时用go.Scatter替代go.Line(Plotly中推荐用Scatter绘制折线)。

内容的提问来源于stack exchange,提问作者Jon Nir

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.29 07:54:52