Here’s my solution to this workout, where I used several Deneb/Vega-Lite features, including:
General:
• used a title block complete with subtitle
• used a transform block to extend the dataset with difference and percent difference calculations
• used a vconcat block to display the composite visual 2 (separate legend and dumbbell chart)
Legend:
• used hard-coded data values (instead of the default [normal] Power BI “dataset”)
• used an ARC mark of radius zero as the visual itself was not desired, just the legend
• used a color block with hard-coded values to both be consistent with the dumbbell chart and to position and configure the legend
Dumbbell Chart:
• used a RULE mark with colour conditional on the difference field to display the “bar” portion of the dumbbell
• used separate CIRCLE marks for the CP and PY to display the “end” portions of the dumbbell
• used a shared encoding block (outside the layer block) for both the Country (y-axis) and the tooltip
Here’s the code:
{
"title": {
"anchor": "start",
"align": "left",
"offset": 10,
"text": "Deneb Workout 08",
"font": "Verdana",
"fontSize": 16,
"fontWeight": "bold",
"fontStyle": "normal",
"subtitle": "Dumbbell Chart",
"subtitleFont": "Verdana",
"subtitleFontSize": 12,
"subtitleFontWeight": "normal",
"subtitleFontStyle": "italic"
},
"data": {"name": "dataset"},
"transform": [
{
"calculate": "datum['Sales CY'] - datum['Sales PY']",
"as": "_sales_difference"
},
{
"calculate": "datum['_sales_difference'] / datum['Sales PY']",
"as": "_sales_difference_percent"
}
],
"vconcat": [
{
"name": "LEGEND",
"width": 800,
"height": 1,
"data": {
"values": [
{
"legend_id": 1,
"legend_size": 1,
"legend_label": "Previous Year"
},
{
"legend_id": 2,
"legend_size": 1,
"legend_label": "Current Year"
}
]
},
"mark": {
"type": "arc",
"radius": 0
},
"encoding": {
"theta": {
"field": "legend_size",
"type": "quantitative"
},
"color": {
"field": "legend_label",
"type": "nominal",
"scale": {
"domain": [
"Current Year",
"Previous Year"
],
"range": ["navy", "skyblue"]
},
"legend": {
"orient": "top-left",
"direction": "horizontal",
"title": null,
"offset": 0,
"labelColor": "black",
"labelFont": "Segoe UI",
"labelFontSize": 12,
"labelFontStyle": "italic",
"symbolSize": 200,
"symbolType": "circle"
}
}
}
},
{
"name": "DUMBBELL_CHART",
"encoding": {
"y": {
"field": "Country",
"type": "nominal",
"sort": {
"op": "sum",
"field": "Sales CY",
"order": "descending"
},
"title": null
},
"tooltip": [
{
"field": "Country",
"type": "nominal"
},
{
"field": "Sales CY",
"type": "quantitative",
"formatType": "pbiFormat",
"format": "$#,##0;($#,##0)"
},
{
"field": "Sales PY",
"type": "quantitative",
"formatType": "pbiFormat",
"format": "$#,##0;($#,##0)"
},
{
"field": "_sales_difference",
"type": "quantitative",
"title": "Difference",
"formatType": "pbiFormat",
"format": "$#,##0;($#,##0)"
},
{
"field": "_sales_difference_percent",
"type": "quantitative",
"title": "% Difference",
"formatType": "pbiFormat",
"format": "#%"
}
]
},
"layer": [
{
"name": "RULE",
"height": 480,
"width": 800,
"mark": {
"type": "rule",
"strokeWidth": 5
},
"encoding": {
"x": {
"field": "Sales PY",
"type": "quantitative",
"title": "Annual Sales",
"axis": {
"format": "$#,0",
"formatType": "pbiFormat",
"tickCount": 6
}
},
"x2": {"field": "Sales CY"},
"color": {
"condition": {
"test": "datum['_sales_difference'] < 0",
"value": "red"
},
"value": "green"
}
}
},
{
"name": "CIRCLE_PY",
"mark": {
"type": "circle",
"size": 200,
"color": "skyblue",
"opacity": 1
},
"encoding": {
"x": {
"field": "Sales PY",
"type": "quantitative"
}
}
},
{
"name": "CIRCLE_CY",
"mark": {
"type": "circle",
"size": 200,
"color": "navy",
"opacity": 1
},
"encoding": {
"x": {
"field": "Sales CY",
"type": "quantitative"
}
}
}
]
}
]
}
Congratulations to all who participated, and good luck.
Greg
Deneb Workout 08 - Dumbbell Chart.pbix (1.7 MB)