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

Altair:基于列表成员关系设置轴标签颜色条件

解决调度图冲突设备Y轴标签高亮问题

方法一:给数据新增标记列(推荐)

在DataFrame中添加一列标记设备是否存在冲突,之后直接在Altair的条件判断中引用该列:

import streamlit as st
import altair as alt
import pandas as pd

data = [
    {"task": "Task 1", "start": 1, "finish": 10, "equipment": "XXX-101"},
    {"task": "Task 2", "start": 9, "finish": 20, "equipment": "XXX-101"},
    {"task": "Task 3", "start": 6, "finish": 8, "equipment": "XXX-102"},
    {"task": "Task 4", "start": 9, "finish": 12, "equipment": "XXX-102"},
    {"task": "Task 5", "start": 13, "finish": 18, "equipment": "XXX-102"},
    {"task": "Task 6", "start": 5, "finish": 15, "equipment": "XXX-103"},
    {"task": "Task 7", "start": 16, "finish": 18, "equipment": "XXX-103"},
    {"task": "Task 8", "start": 6, "finish": 8, "equipment": "XXX-104"},
    {"task": "Task 9", "start": 4, "finish": 12, "equipment": "XXX-104"},
    {"task": "Task 10", "start": 11, "finish": 16, "equipment": "XXX-104"},
]
dataframe = pd.DataFrame(data)

equipment_has_clashes = ["XXX-101", "XXX-104"]

# 新增列标记是否有冲突
dataframe['has_clash'] = dataframe['equipment'].isin(equipment_has_clashes)

chart = (
    alt.Chart(dataframe)
    .mark_bar(height=20)
    .encode(
        x=alt.X("start").title("time"),
        x2=("finish"),
        y=alt.Y(
            "equipment",
            axis=alt.Axis(
                labelColor=alt.condition(
                    # 直接引用新增的标记列
                    'datum.has_clash',
                    if_true=alt.value("red"),
                    if_false=alt.value("black"),
                )
            ),
        ),
        tooltip=[alt.Tooltip(t) for t in ["task", "equipment", "start", "finish"]],
        color=alt.Color("task", type="nominal").scale(scheme="category20"),
    )
    .properties(height=alt.Step(30))
    .configure_view(strokeWidth=1)
    .configure_axis(domain=True, grid=True)
    .interactive()
)

st.altair_chart(chart, use_container_width=True)

方法二:直接在Altair表达式中判断成员关系

如果不想修改原始数据,可以用Vega-Lite的表达式语法,通过indexof函数检查设备是否在冲突列表中(返回值不等于-1则表示存在):

import streamlit as st
import altair as alt
import pandas as pd

data = [
    {"task": "Task 1", "start": 1, "finish": 10, "equipment": "XXX-101"},
    {"task": "Task 2", "start": 9, "finish": 20, "equipment": "XXX-101"},
    {"task": "Task 3", "start": 6, "finish": 8, "equipment": "XXX-102"},
    {"task": "Task 4", "start": 9, "finish": 12, "equipment": "XXX-102"},
    {"task": "Task 5", "start": 13, "finish": 18, "equipment": "XXX-102"},
    {"task": "Task 6", "start": 5, "finish": 15, "equipment": "XXX-103"},
    {"task": "Task 7", "start": 16, "finish": 18, "equipment": "XXX-103"},
    {"task": "Task 8", "start": 6, "finish": 8, "equipment": "XXX-104"},
    {"task": "Task 9", "start": 4, "finish": 12, "equipment": "XXX-104"},
    {"task": "Task 10", "start": 11, "finish": 16, "equipment": "XXX-104"},
]
dataframe = pd.DataFrame(data)

equipment_has_clashes = ["XXX-101", "XXX-104"]

chart = (
    alt.Chart(dataframe)
    .mark_bar(height=20)
    .encode(
        x=alt.X("start").title("time"),
        x2=("finish"),
        y=alt.Y(
            "equipment",
            axis=alt.Axis(
                labelColor=alt.condition(
                    # 使用Vega-Lite表达式判断成员关系
                    f"indexof({equipment_has_clashes}, datum.equipment) !== -1",
                    if_true=alt.value("red"),
                    if_false=alt.value("black"),
                )
            ),
        ),
        tooltip=[alt.Tooltip(t) for t in ["task", "equipment", "start", "finish"]],
        color=alt.Color("task", type="nominal").scale(scheme="category20"),
    )
    .properties(height=alt.Step(30))
    .configure_view(strokeWidth=1)
    .configure_axis(domain=True, grid=True)
    .interactive()
)

st.altair_chart(chart, use_container_width=True)

说明

  • 方法一逻辑清晰,便于后续扩展(比如基于该列做其他可视化调整),且不需要熟悉Vega-Lite的表达式语法。
  • 方法二无需修改原始数据,但要遵循Vega-Lite的表达式规则:indexof函数第一个参数是数组,第二个是要查找的元素,返回索引位置,不存在则返回-1。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.06 01:10:18