I wanted to create a vega chart using the following spec…
The data input is called “Asset”, and three input properties (all are string type) called “equipmentId”, “riskLevel” and “ComplianceStatus” are used. There are NULL values for “riskLevel” and “complianceStatus”, these should be handled by labelling any NULL value as “N/A” instead. I need the spec to create a bar chart which shows how many “equipmentId” items there are as a percentage of how many have “Compliant” for “complianceStatus”, grouped by “riskLevel”. There should also be conditional formatting for the bars, if the percentage is below 85% the bar is red, if it’s 85% or greater but less than 90% it’s yellow and if it’s greater than 90% it’s green.
From the above, the following vega spec has been used, but it only renders the axes (as shown in the screenshot). Does anyone know why the bars aren’t rendering? I’ve included a sample of the data for these records as well, for full context.
Sample of record data
{
"equipmentId": "biomed-8DD49035-5F23-4FFC-9271-8A4ECDA9BFA4",
"complianceStatus": "Compliant",
"riskLevel": "4"
},
{
"equipmentId": "biomed-91FD8361-56B1-4786-A4DB-6520BABC3A76",
"complianceStatus": "N/A",
"riskLevel": "4"
}
Screenshot of Chart
Vega Spec
{
“$schema”: “https://vega.github.io/schema/vega/v5.json”,
“description”: “Shows % of compliant equipment by risk level with conditional colouring.”,
“width”: 400,
“height”: 300,
“padding”: 5,
“data”: [
{
"name": "Asset"
},
{
"name": "cleanData",
"source": "Asset",
"transform": \[
{
"type": "formula",
"as": "riskLevel",
"expr": "datum.riskLevel == null ? 'N/A' : datum.riskLevel"
},
{
"type": "formula",
"as": "complianceStatus",
"expr": "datum.complianceStatus == null ? 'N/A' : datum.complianceStatus"
}
\]
},
{
"name": "totalByRisk",
"source": "cleanData",
"transform": \[
{
"type": "aggregate",
"groupby": \["riskLevel"\],
"ops": \["count"\],
"fields": \["equipmentId"\],
"as": \["total"\]
}
\]
},
{
"name": "compliantByRisk",
"source": "cleanData",
"transform": \[
{
"type": "filter",
"expr": "datum.complianceStatus === 'Compliant'"
},
{
"type": "aggregate",
"groupby": \["riskLevel"\],
"ops": \["count"\],
"fields": \["equipmentId"\],
"as": \["compliant"\]
}
\]
},
{
"name": "complianceStats",
"source": "totalByRisk",
"transform": \[
{
"type": "lookup",
"from": "compliantByRisk",
"key": "riskLevel",
"fields": \["riskLevel"\],
"values": \["compliant"\],
"as": \["compliant"\],
"default": 0
},
{
"type": "formula",
"as": "compliantPct",
"expr": "datum.total > 0 ? (datum.compliant / datum.total) \* 100 : 0"
},
{
"type": "formula",
"as": "complianceBand",
"expr": "datum.compliantPct < 85 ? 'low' : datum.compliantPct < 90 ? 'medium' : 'high'"
}
\]
}
],
“scales”: [
{
"name": "xscale",
"type": "band",
"domain": {"data": "complianceStats", "field": "riskLevel"},
"range": "width",
"padding": 0.1
},
{
"name": "yscale",
"domain": \[0, 100\],
"range": "height"
},
{
"name": "colorScale",
"type": "ordinal",
"domain": \["low", "medium", "high"\],
"range": \["red", "yellow", "green"\]
}
],
“axes”: [
{"orient": "bottom", "scale": "xscale", "title": "Risk Level"},
{"orient": "left", "scale": "yscale", "title": "% Compliant"}
],
“marks”: [
{
"type": "rect",
"from": {"data": "complianceStats"},
"encode": {
"enter": {
"x": {"scale": "xscale", "field": "riskLevel"},
"width": {"scale": "xscale", "band": 1},
"y": {"scale": "yscale", "field": "compliantPct"},
"y2": {"scale": "yscale", "value": 0},
"fill": {"scale": "colorScale", "field": "complianceBand"}
}
}
},
{
"type": "text",
"from": {"data": "complianceStats"},
"encode": {
"enter": {
"x": {"scale": "xscale", "field": "riskLevel", "band": 0.5},
"y": {"scale": "yscale", "field": "compliantPct", "offset": -5},
"text": {"signal": "format(datum.compliantPct, '.1f') + '%'" },
"align": {"value": "center"},
"baseline": {"value": "bottom"},
"fill": {"value": "black"},
"fontSize": {"value": 12}
}
}
}
]
}
