如何在Power BI的Deneb哑铃图中添加垂直平均线?
在Deneb(Power BI)中为哑铃图添加全局平均值垂直线的问题
我正在Power BI的Deneb中制作哑铃图,想要添加一条垂直线代表所有数值的平均值。参考类似方案后,得到的却是多条平均值水平线,而非期望的单条垂直线(效果见下图)。我需要的是一条代表整体平均值0.73的垂直线。

复现数据集
| Row ID | Categories | Factor | Value | Grand Mean |
|---|---|---|---|---|
| 1 | Category 1 | One | 0.5 | 0.73 |
| 2 | Category 2 | One | 0.75 | 0.73 |
| 3 | Category 1 | Two | 0.7 | 0.73 |
| 4 | Category 2 | Two | 0.9 | 0.73 |
当前使用的Vega-Lite代码
{ "$schema": "https://vega.github.io/schema/vega-lite/v5.json", "description": "Dumbbell chart with labels", "data": {"name": "dataset"}, "transform": [ {"joinaggregate": [{ "op": "mean", "field": "Grand Mean", "as": "Grand Mean" }] }], "encoding": { "x": { "field": "Value", "type": "quantitative", "title": "Factor Value"//, }, "y": { "field": "Categories", "type": "nominal", "title": null//, } }, "layer": [ { "mark": "line", "encoding": { "detail": { "field": "Categories", "type": "nominal" }, "color": {"value": "gray"} } }, { "mark": { "type": "point", "filled": true }, "encoding": { "color": { "field": "Factor", "type": "ordinal", "legend": { "title": null, "offset": 0 }, "scale": { "domain": ["One", "Two"], "range": ["#6ba5cd", "#8e946a"] }, "title": "Legend" }, "size": {"value": 300}, "opacity": {"value": 1} } }, { "mark": { "type": "text", "align": "center", "baseline": "bottom", "dy": -15 }, "encoding": { "detail": { "field": "Categories", "type": "nominal" }, "text": { "field": "Factor", "type": "ordinal" } } }, // adding in a red line: {"mark": {"type": "rule", "color": "red" }, "encoding": { "x": { "field": "Grand Mean", "type": "quantitative"} } } ] }
问题原因及修复方案
问题根源
当前代码中,rule标记的图层继承了顶层的y编码(绑定到Categories字段),所以Vega-Lite会为每个分类生成一条水平线。同时,你用joinaggregate计算平均值的方式也冗余了——数据集里已经有全局平均值Grand Mean,不需要再重复计算。
修复步骤
- 移除冗余的
joinaggregate转换:因为数据集中已经包含全局平均值Grand Mean,直接使用即可。 - 为垂直线图层重置y编码:在
rule图层的编码中添加y配置,设置为{"type": "nominal", "domain": {"union": true}},覆盖顶层的分类绑定,让垂直线跨越整个y轴范围,变成全局的垂直线。
修复后的完整代码
{ "$schema": "https://vega.github.io/schema/vega-lite/v5.json", "description": "Dumbbell chart with labels", "data": {"name": "dataset"}, "encoding": { "x": { "field": "Value", "type": "quantitative", "title": "Factor Value" }, "y": { "field": "Categories", "type": "nominal", "title": null } }, "layer": [ { "mark": "line", "encoding": { "detail": { "field": "Categories", "type": "nominal" }, "color": {"value": "gray"} } }, { "mark": { "type": "point", "filled": true }, "encoding": { "color": { "field": "Factor", "type": "ordinal", "legend": { "title": null, "offset": 0 }, "scale": { "domain": ["One", "Two"], "range": ["#6ba5cd", "#8e946a"] }, "title": "Legend" }, "size": {"value": 300}, "opacity": {"value": 1} } }, { "mark": { "type": "text", "align": "center", "baseline": "bottom", "dy": -15 }, "encoding": { "detail": { "field": "Categories", "type": "nominal" }, "text": { "field": "Factor", "type": "ordinal" } } }, // 全局平均值垂直线 { "mark": {"type": "rule", "color": "red"}, "encoding": { "x": {"field": "Grand Mean", "type": "quantitative"}, "y": {"type": "nominal", "domain": {"union": true}} } } ] }
额外说明
如果你的数据集里没有预先计算好的Grand Mean,可以用独立数据集计算全局平均值后绘制垂直线,示例如下:
// 在layers外添加单独的平均值计算 "data": [ {"name": "dataset"}, {"name": "mean-data", "source": "dataset", "transform": [{"aggregate": [{"op": "mean", "field": "Value", "as": "Grand Mean"}]}]} ], // 垂直线图层改为使用mean-data { "mark": {"type": "rule", "color": "red"}, "data": {"name": "mean-data"}, "encoding": { "x": {"field": "Grand Mean", "type": "quantitative"}, "y": {"type": "nominal", "domain": {"union": true}} } }
内容的提问来源于stack exchange,提问作者JR87
相关产品推荐
相关产品推荐

