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

如何在Altair中实现双折线图中途变色及自定义颜色与图例?

在Altair中实现折线中途变色并自定义颜色与图例

希望绘制两条折线,每条折线在post字段切换(0→1)时改变颜色,同时自定义各阶段颜色并添加清晰的图例。

测试数据代码

import pandas as pd
from datetime import datetime
import numpy as np

data_list = [(['1', '2']*20)*2,
             [0]*20+[1]*20,
             np.repeat(pd.date_range(datetime.today(), periods=20).tolist(), 2),
             np.random.normal(size=40)
            ]
data_df = pd.DataFrame(data_list).transpose()
data_df.columns = ['group', 'post', 'datetime', 'value']

之前的尝试问题

  1. 第一次尝试:分别绘制post=0和post=1的折线,虽实现颜色区分,但折线被拆分为独立线条,且图例重复显示同一组的前后阶段。
  2. 第二次尝试:通过图层叠加实现了折线中途变色,但无法自定义阶段颜色,也无法生成符合需求的图例。

解决方案

核心是通过组合group与post生成新标签,用该标签控制颜色,同时用detail字段保证折线连续性,最终实现自定义颜色和清晰图例。

完整代码

import altair as alt
import pandas as pd
from datetime import datetime
import numpy as np

# 生成并预处理测试数据
data_list = [(['1', '2']*20)*2,
             [0]*20+[1]*20,
             np.repeat(pd.date_range(datetime.today(), periods=20).tolist(), 2),
             np.random.normal(size=40)
            ]
data_df = pd.DataFrame(data_list).transpose()
data_df.columns = ['group', 'post', 'datetime', 'value']
# 转换数据类型避免编码问题
data_df['post'] = data_df['post'].astype(int)
data_df['value'] = data_df['value'].astype(float)

# 图表基础配置
PROPERTIES = {"height": 200, "width": 800}

# 自定义各阶段颜色映射
color_map = {
    "Group A (前期)": "#F44E4E",
    "Group A (后期)": "#F20505",
    "Group B (前期)": "#0442BF",
    "Group B (后期)": "#63CAF2"
}

# 绘制变色折线
line_chart = alt.Chart(data_df).transform_calculate(
    # 生成包含组和阶段的标签
    stage_label="datum.group == '1' ? (datum.post == 0 ? 'Group A (前期)' : 'Group A (后期)') : (datum.post == 0 ? 'Group B (前期)' : 'Group B (后期)')"
).mark_line(opacity=0.8, strokeWidth=3, strokeCap='round').encode(
    x=alt.X("datetime:T", title=None),
    y=alt.Y("value:Q", title=None),
    # 用组合标签控制颜色,绑定自定义比例尺
    color=alt.Color(
        "stage_label:N",
        scale=alt.Scale(domain=list(color_map.keys()), range=list(color_map.values())),
        title=None,
        legend=alt.Legend(orient="bottom-left")
    ),
    # 用原始group字段保证同一组的前后阶段是同一条折线
    detail=alt.Detail("group:N")
)

# 绘制背景灰色区域
area_pre = alt.Chart(data_df).mark_rect(opacity=0.5).encode(
    x=alt.X("min(datetime):T", title=None),
    x2=alt.X2("max(datetime):T"),
    y=alt.value(0),
    y2=alt.value(PROPERTIES["height"]),
    fill=alt.Color(scale=alt.Scale(range=["lightgray"]), legend=None)
).transform_filter(alt.datum.post == 0)

area_post = alt.Chart(data_df).mark_rect(opacity=0.5).encode(
    x=alt.X("min(datetime):T", title=None),
    x2=alt.X2("max(datetime):T"),
    y=alt.value(0),
    y2=alt.value(PROPERTIES["height"]),
    fill=alt.Color(scale=alt.Scale(range=["lightgray"]), legend=None)
).transform_filter(alt.datum.post == 1)

# 组合所有图层
final_chart = alt.layer(area_pre + area_post, line_chart).properties(**PROPERTIES)
final_chart

关键说明

  • 组合标签stage_label:通过计算字段将group和post合并为可读标签,既用于颜色映射,也让图例清晰展示每个阶段。
  • detail字段:指定detail="group:N",确保同一组的前后数据被识别为同一条折线,不会因颜色分组而断开。
  • 自定义颜色比例尺:直接将标签与颜色绑定,完全控制各阶段的显示颜色。
  • 背景区域:通过两个过滤后的矩形图层,覆盖post=0和post=1的整个时间范围,实现背景分区效果。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.14 13:55:20