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

如何在Altair的分层分面图表中合并多个颜色图例?

Altair分面分层图表重复颜色图例的解决方法

问题描述

在Altair中,将两个使用不同颜色刻度的图表分层后进行分面处理时,会出现颜色图例重复的问题:

  • 仅使用单一颜色刻度时,图例可正常合并为一个;
  • 引入第二种独立刻度(如一组点用连续刻度表示coverage,一组线用离散刻度表示model),每个分面都会重复显示这两个图例。

示例中estimate(strokeDash)图例仅显示一次,但coverage和model图例在每个分面重复出现。

可复现代码

import pandas as pd
import numpy as np
import altair as alt
np.random.seed(0)

## simulate some timeseries data
# date
data = pd.DataFrame({
    "date": pd.date_range("2024-01-01", "2024-04-30"),
})
# true value (just some weekday effects, log-linear growth, and noise)
data["y"] = (
    np.log(np.arange(data.shape[0])+1)
    + np.random.normal(scale=3, size=7)[data["date"].dt.weekday]
    + np.random.normal(size=data.shape[0])
)
# coverage of the data (0 to 1, skewed towards 1)
data["coverage"] = np.random.beta(3, 1, size=data.shape[0])
# observed value (truth x coverage)
data["y_obs"] = data["y"] * data["coverage"]


## fake some simple model fits
# model A: 7-day rolling quantile
model_a = pd.DataFrame({
    "model": "A",
    "date": data["date"],
    "median": data["y"].rolling(7).median(),
    "p90": data["y"].rolling(7).quantile(.9)
})
# model B: 21-day rolling quantile
model_b = pd.DataFrame({
    "model": "B",
    "date": data["date"],
    "median": data["y"].rolling(14).median(),
    "p90": data["y"].rolling(14).quantile(.9)
})
# combine models
models = pd.concat([model_a, model_b]).melt(id_vars=["model", "date"], var_name="estimate")

## create the chart
# combine all data so one source can be used for the layered chart and faceted by month
source = pd.concat([models, data])
source["month"] = source["date"].dt.month
# overall chart
chart = alt.Chart(
    source,
    title = "Model Fits"
)
# predictions
lines = (
    chart
    .transform_filter(alt.datum.model) # filter to model results
    .mark_line(opacity = .7)
    .encode(
        x = alt.X("date:T"), 
        y = alt.Y("value:Q"), 
        color = alt.Color("model"),
        strokeDash = alt.StrokeDash("estimate"),
     )
)
# data
points = (
    chart
    .transform_filter(alt.datum.y_obs) # filter to data
    .mark_point(filled = True)
    .encode(
        x = alt.X("date:T"),
        y = alt.Y("y_obs:Q").title("value"),
        color = alt.Color("coverage:Q").scale(domain=[0,1], scheme="spectral"),
    )
)
# combine them and facet
alt.layer(lines, points).facet("month", columns = 2).resolve_scale(x="independent")

解决方案

要解决图例重复问题,只需在分面后的图表配置中添加.resolve_legend(color='independent'),明确让两个独立的颜色图例全局仅显示一次,而非每个分面重复渲染。

修改后的最终代码行:

alt.layer(lines, points).facet("month", columns=2).resolve_scale(x="independent").resolve_legend(color='independent')

如果需要更清晰的图例标题,还可以在每个颜色编码中显式指定图例属性,再结合上述配置:

# 线条的颜色编码
color = alt.Color("model", legend=alt.Legend(title="Model"))
# 点的颜色编码
color = alt.Color("coverage:Q", scale=alt.Scale(domain=[0,1], scheme="spectral"), legend=alt.Legend(title="Coverage"))

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.27 15:03:13