如何在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
相关产品推荐
相关产品推荐

