如何在Vega-Lite中为堆叠条形图分配自定义颜色并配置图例
问题描述
在Vega-Lite中构建了包含2个堆叠条形图、1个普通条形图及1个折线图的分层图表,遇到两个问题:
- 尝试通过
scale与domain声明为堆叠条形图分配自定义颜色,但未达到预期效果; - 希望在图例中显示
Bikes Sales、Car Sales、Bike Sales LY、Car Sales LY,当前无法实现。
当前代码如下:
{ "$schema": "https://vega.github.io/schema/vega-lite/v5.json", "data": { "values": [ { "Month": 1, "Category": "Bikes", "Sales": 100, "Sales LY": 90, "Target": 95, "Volume": 300 }, { "Month": 1, "Category": "Cars", "Sales": 560, "Sales LY": 800, "Target": 880, "Volume": 1200 }, { "Month": 2, "Category": "Bikes", "Sales": 130, "Sales LY": 170, "Target": 190, "Volume": 450 }, { "Month": 2, "Category": "Cars", "Sales": 600, "Sales LY": 665, "Target": 680, "Volume": 1200 }, { "Month": 3, "Category": "Bikes", "Sales": 200, "Sales LY": 150, "Target": 165, "Volume": 400 }, { "Month": 3, "Category": "Cars", "Sales": 750, "Sales LY": 1000, "Target": 1100, "Volume": 1200 }, { "Month": 4, "Category": "Bikes", "Sales": 80, "Sales LY": 105, "Target": 120, "Volume": 500 }, { "Month": 4, "Category": "Cars", "Sales": 800, "Sales LY": 600, "Target": 660, "Volume": 1200 } ] }, "transform": [ {"calculate": "'Volume'", "as": "Volume Legend"}, {"calculate": "'Target'", "as": "Target Legend"}, {"calculate": "datum.Category", "as": "Category2"} ], "height": 300, "width": 300, "layer": [ { "name": "SALES", "mark": {"type": "bar", "xOffset": 0, "size": 10}, "encoding": { "x": {"field": "Month", "type": "ordinal", "axis": {"labelAngle": 0}}, "y": {"field": "Sales", "type": "quantitative"}, "color": { "field": "Category", "type" : "nominal", "scale": {"domain": [ "Bikes","Cars"], "range": ["#4CD964", "#39A34B"]} } } }, { "name": "SALES LY", "mark": {"type": "bar", "xOffset": -11, "size": 10}, "encoding": { "x": {"field": "Month", "type": "ordinal", "axis": {"labelAngle": 0}}, "y": {"field": "Sales LY", "type": "quantitative", "axis": null}, "color": { "field": "Category2", "type" : "nominal", "scale": {"domain": [ "Bikes","Cars"], "range": [ "#5AC8FA", "#4496BC" ]} } } }, { "name": "TARGET", "mark": {"type": "bar", "xOffset": 11, "size": 10}, "encoding": { "x": {"field": "Month", "type": "ordinal", "axis": {"labelAngle": 0}}, "y": {"aggregate": "sum", "field": "Target", "type": "quantitative", "axis": null}, "color": { "field": "Target Legend", "scale": { "range": ["#FFCC00" ]}, "legend": {"title": ""} }} }, { "name": "VOLUME", "mark": {"type": "line"}, "encoding": { "x": {"field": "Month", "type": "ordinal"}, "y": {"aggregate": "sum", "field": "Volume", "type": "quantitative"}, "stroke": { "field": "Volume Legend", "scale": {"range": ["green"]}, "legend": {"title": ""} } } } ], "resolve": {"scale": {"y": "independent"}} }
当前效果:
解决方案
核心问题分析
- 自定义颜色失效:每个图层单独定义颜色比例尺,导致颜色映射不统一,且未将销售类型(当前/去年)与类别关联;
- 图例条目缺失:未生成包含销售类型的唯一字段,无法让图例识别出
Bikes Sales等目标条目。
修改方案及代码
{ "$schema": "https://vega.github.io/schema/vega-lite/v5.json", "data": { "values": [ { "Month": 1, "Category": "Bikes", "Sales": 100, "Sales LY": 90, "Target": 95, "Volume": 300 }, { "Month": 1, "Category": "Cars", "Sales": 560, "Sales LY": 800, "Target": 880, "Volume": 1200 }, { "Month": 2, "Category": "Bikes", "Sales": 130, "Sales LY": 170, "Target": 190, "Volume": 450 }, { "Month": 2, "Category": "Cars", "Sales": 600, "Sales LY": 665, "Target": 680, "Volume": 1200 }, { "Month": 3, "Category": "Bikes", "Sales": 200, "Sales LY": 150, "Target": 165, "Volume": 400 }, { "Month": 3, "Category": "Cars", "Sales": 750, "Sales LY": 1000, "Target": 1100, "Volume": 1200 }, { "Month": 4, "Category": "Bikes", "Sales": 80, "Sales LY": 105, "Target": 120, "Volume": 500 }, { "Month": 4, "Category": "Cars", "Sales": 800, "Sales LY": 600, "Target": 660, "Volume": 1200 } ] }, "transform": [ {"calculate": "'Volume'", "as": "Volume Legend"}, {"calculate": "'Target'", "as": "Target Legend"}, // 生成包含销售类型的类别字段,用于图例显示 {"calculate": "datum.Category + ' Sales'", "as": "Sales Category"}, {"calculate": "datum.Category + ' Sales LY'", "as": "Sales LY Category"} ], "height": 300, "width": 300, // 顶层定义全局统一的颜色比例尺,包含所有图例项 "encoding": { "color": { "type": "nominal", "scale": { "domain": ["Bikes Sales", "Car Sales", "Bikes Sales LY", "Car Sales LY", "Target", "Volume"], "range": ["#4CD964", "#39A34B", "#5AC8FA", "#4496BC", "#FFCC00", "green"] } } }, "layer": [ { "name": "SALES", "mark": {"type": "bar", "xOffset": 0, "size": 10}, "encoding": { "x": {"field": "Month", "type": "ordinal", "axis": {"labelAngle": 0}}, "y": {"field": "Sales", "type": "quantitative"}, "color": {"field": "Sales Category"} } }, { "name": "SALES LY", "mark": {"type": "bar", "xOffset": -11, "size": 10}, "encoding": { "x": {"field": "Month", "type": "ordinal", "axis": {"labelAngle": 0}}, "y": {"field": "Sales LY", "type": "quantitative", "axis": null}, "color": {"field": "Sales LY Category"} } }, { "name": "TARGET", "mark": {"type": "bar", "xOffset": 11, "size": 10}, "encoding": { "x": {"field": "Month", "type": "ordinal", "axis": {"labelAngle": 0}}, "y": {"aggregate": "sum", "field": "Target", "type": "quantitative", "axis": null}, "color": {"field": "Target Legend"} } }, { "name": "VOLUME", "mark": {"type": "line"}, "encoding": { "x": {"field": "Month", "type": "ordinal"}, "y": {"aggregate": "sum", "field": "Volume", "type": "quantitative"}, "color": {"field": "Volume Legend"} } } ], "resolve": {"scale": {"y": "independent"}} }
修改说明
- 数据转换:新增
Sales Category和Sales LY Category字段,将类别与销售类型组合,生成图例所需的完整名称; - 全局颜色配置:在顶层
encoding中定义统一的颜色映射,确保所有图层的颜色遵循同一规则,解决自定义颜色失效问题; - 图层关联:各图层的
color字段直接映射到生成的组合字段,自动关联全局颜色配置,图例将自动显示所有目标条目。
内容的提问来源于stack exchange,提问作者Deston
相关产品推荐
相关产品推荐

