Reproduction of "The Mundigl Bullets" using Deneb & Vega-Lite
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"$schema": "https://vega.github.io/schema/vega-lite/v5.json", | |
"usermeta": { | |
"deneb": { | |
"build": "1.3.0.0", | |
"metaVersion": 1, | |
"provider": "vegaLite", | |
"providerVersion": "5.2.0" | |
}, | |
"interactivity": { | |
"tooltip": true, | |
"contextMenu": true, | |
"selection": false, | |
"highlight": false, | |
"dataPointLimit": 50 | |
}, | |
"information": { | |
"name": "Mundigl Bullet Chart", | |
"description": "An interpretation of the bullet chart variations by Robert Mundigl: https://www.clearlyandsimply.com/clearly_and_simply/2017/07/variations-of-alternative-bullet-graphs-in-excel.html", | |
"author": "Daniel Marsh-Patrick (inspired by Robert Mundigl)", | |
"uuid": "c7017285-b3cb-4633-b9ef-cb3cefa8c2fb", | |
"generated": "2022-08-20T05:23:38.967Z", | |
"previewImageBase64PNG": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAJYAAABKCAYAAABZ/a22AAAVyElEQVR4Xu1dDXRV1ZXe5/68927eC3kvCfkjQEBiaySADT+FzowyU6tTrC5K84JaLf0DbZVqyxR1FqK1U6etzNLIdJZMWxAVbaLjzLJrOR2HTltH1FVCVSAVQiAm5P/nJXm/9717z561LzzmGUjy7vvJe0DOWqwAOWefffb97jnn7vPtfRhMl2kLpMECLA0yp0XGWAARhe5du9YLivLfJXfe2Xe5GCcpYDU0NKwFgM2Xi7ESGSdjjFV0ds4bnDWrexQxmIiMMW1EANCTlYOITXV1dVuSlTNe+3iAxWpra+XGxsYwCdm48Qs5u3a9RgbCxsbGexGxPla4oijgcDiAcw6Dg4Pp0js75eo6AGMAggBw9u9MFKG8uxsGS0ogkKDWTqcTAoEAhMNhsFqtYLPZDEmhUAhUVU1QKrzhdrs/l2jjydp9DFhf+fKX14Cot6EmLBQAPuKcL+OofaSB2GUTRdUfDg85FHmpDtLBvXv3dhKwbDZb/bx580AU6UUCY+AELBpwR0cHnD59ejIdLvrf27q6IJKXB/LwMCAQthgAInBZhkhxMcwbHYWKm26Ckx99BENDQ6bGS3Z1uVyGzJycHOPvkUgEBEGA4eFhaG9vP9OfiVJdXQ09PT0f1NTULDbRzFTVj2m04fbbl3ERPsE4IgPBr4HWJ6KoAIAoMtar+f2nIVdZxBj2Pfvsi0ejM9bixYuNt4feJAIVIhp/Tp06RQMwpdDFVplxDtLICEh+PyBjBpjop6BpgKJoAGt2by8IS5bAcCBgzDzxFrIh2bSiogJoJcjLyzNeWJ/PB5IkwejoKLS2tpoGVmlpKQwMDPxhzZo118ari9l65qA+RnrsUlhcXAy9vb1m+79k6rNIhF4/QFoGYwrNJskshQQukpGfn2+Ayk8ARpoXz86MiVtw6pZCszo2NDQsR8TPm213OdWXJEmo7Oq6vr+09OCArmfNppMx1up2u59L17NIasZKl1KXmlxEzAUAP2OMX4xjQ0Sp/6WXVs5cv/4AYyyuL9KkgDU9Y12MMDmjc11d3SPxao+IrpPbt/90/qOP3scY88XTLh5gfczdUFtba3G5XLhr167IhdwNtKmkz+OBgYF4+p+ukyELeDwey6ZNmyLUPSJ+anh4+Cs2m61QVdUg51xXFOUtRVH2nv296+RDDz0+/0c/2kLAOlhTk1PT1BRsqqlRapqaQk01NaItGGRXNzdH6HvY2P/Fjised0NOjqUiEAgfamxsDMa6G4LBIBQUFIDdbje+VuiT+MiRIxky23S3k1lA1/W7JUmyC4Lw8urVq3/S0dFR63K5uM/nE2hy4JwPOZ3Ob7/11lvvAMA/XHnkCCx8+OG73rvmGgms1muFYLAJLBYnMFbMEa2c85AkCJ2LDx48dh6wJnM3eFW1y2GzVaOud+zZt68l1t0gy7Lx5aJpGoyMjBg/33///cnGN/37zFlgPSKWVVZW/nbu3LlPeDyev9E0DW02GyPntq7rAw6H49v79+9/W1GUBz959OiMqm3b7m5aulQESfqUVVVV3WIZYADFIIp2PRQKMoul65p33205D1hmxzjtbjBrseypP2YppKO5uwCgkFZGAOOQ4GXGmHGqYuyxYpZC+r8jVVWOhc3N4+634tljjWuN6c179gDFrCZmN++ntm//6bwUb97N6py19YlpAAAzGGPDWatkFiqGiGLf7t0rir761XfidZlcVjNWocWSP7O9fVlLefkbmqalzaeEiERqkAHAOLhPV6GH7Ha7f5Au+cnIjQdYk7Ib6AyLjhnoa5AKnWvRgWkm2A10tEJndIyOQuggmDHj05f+T2EMCjo7oXPWrHPHIskYb2zbsSwEsgMdx9DHDG2I01A0t9tNAM66YsrdEPJ6B+U8+3xRhIE9e178kDbvpaWl9UVFRcbBKBmSAEYn7/SHDqHJqFNWOAfL4CAIkQgQwHS7HYTgGQpUZOZMsCgKlI6OAq+uhu7u7pSpRWPWdR2uuOIKA0BkB2IhkAuG2AmdnZ3Q15dajl9JSQm9yNr111+f/cCazN3QPTj4YVGRayGAPvzss79qJWCVlZXV0yDpFJ7ARW8o8YYIWMRsmFJHKQHL4wHJ5zvjpaMHnpMDgqpCuLAQrDk5cJXTCUpVFXzwwQcpBRYBilgDZAuarenAmIAV5aWRHczSWyZScO7cuSDLMlZWVn781Dtlo0pOUDxL4bg9ZKO7gWgsRLJD+fwXOZ1LYZSFQDMVvVhRFkIqwXSBB3FxLIVmMXqxUZMdgmCb2d4+q2327JMY5Z6YHXR21dfdbvdns0ulM9okNWNl44Am0mmkoSHf1939ubLNmxvi/Wy+2MYYj76IaEznjDHjrDAdJSlgNTQ0zGKMVaZDsUtVpiRJ761duzajfrT2+voNXNeFivvv/2W67BwPsD7mbohV5ELshhkzZhi0WfpKmtIvwnRZKMVyEfGv6+rq/seMWET89NDQ0DqHwxH0+XxKTk6OS9M0O2PMb7VaG2RZ/i8z8k4/8cQdNF2Vf+97BnshthypqrJAczOEampwaVNTwjOaKXfDkNfblpeXN9eqaf0/f/HFXgLWzJkz64mW3N/fb7AbcnNzDYYDBQ3Q/10OwRRmHirn/AZyQSDim/G2u+mmm54JBAK3EaXFarXm9PX1oaqqgtVqZaIoHi0rK6t9/fXX2+KRp+v6oiX9/ctyI5FRAlbLggVWn8tVo3o8RyxOZy0w1iZy7tMFwZrr8bxbeeJEQmFApoIppJyc5rDfX7PnhRfejYZ/5ebm1s+ePdvw3VDUCDEcCFgUXEERJOTDmS7/bwFEfJIxtoRz/r147FJQUJCzfPnyhwYGBm5UFAXP0lr46OioQAC1WCynVFX9bnNzc3s88gBgU66mVS7u7d1DwPqgutqFjM1CRSnTAT7PdP23AmKIWyxqbn//OykBVpyKnauWje4Gs2OY6vq0FFoslj+Z2Wch4gMA8OVwOFwhiqJXFEXizpP/in7+gjG2J95xvPrqq85lra1fiF0K8brrpLa2NmleW1soXjmT1YtnjzWujAvtsSbr8HL/fSJ7rFTbbKI9Vqr6SgpYqVIi03Lo8zudn96ZHt/Y/rtefPEvJUFgRXV1f0iXbpc9sIgS0lVff79eXPzqnPXrWycz9GuvvZbjcDjCq1ev1hoaGhzNzc2BRx55JC0nzJPpkujviX1BbRljZwIU01CSAtbYpbCwsNDYwBMtOZsKRSVzOhjnHAgBtDkh1gPlWaDcCrN6emCoqAgC44SqxwaI0t/py5eK1+ud8PyPMba5trb26WyyxVTpEg+wJqTNiKJYv2TJEsPA9IcOn+kAlr4ST5w4kfJT/UQMI3k8hm4ECtnnAyD2A2Og2e1GCHwUWBGLxQgCGVvohSEGBx2qU94DenHoBSKAvf322xcEF8UAaJo2DSwy5mRROsN+f4fTaXMKIQj/8qWXumjGqqioqI/SRYjdQMAiJymVo0ePZt7dgAiS1wtiKGTkVWCadibPgiCAbrMZwJozNARX33YbHDt+3ABMbCEwUr6FBQsWGLkTKDcFsRaIzUEgbG5uvuAMvWrVKjh8+PATy5cv/7tEXoaLvY0pP5ZXVVsVRaoOBrX3ouFf0TRG2Z67YaLcCjRjecvLIcjYBWcsAhf55iwWy7lsMbGshQsxGIg6EwgEpmesRN6QS8HdQKCYbI+ViG3Obo6ngZWI8S6FQ2hRFIVP9vTU9ufn/2+fKKb0mAARW9xud0plJvKcMtEmns17JvSa0j4R0ULs5XR+fo/Zt1UBQAdjzJvMQHt3775e17Shsm9+sykZOelomxSwxhL9CgoK7KOjo6FIJBJXRpJ0DCidMt1u9+pE5CPifJ/Pdzsiqrm5uZT6cM3IyIjfYrH0qqr6vtPp3JUIyNp//ONvcYCeiq1b/w0BGOVSWNrUdC6zGwIIlFchGZZCIuM1tgFxNJyQNhPrbqDPcHIzRL8OT548eS5yJ45+LoYqOW6323SCWkS83+fzPTowMCA5nc7gsWPHnAUFBcRMwFAoFLrqqqu+zhh7yawBYoHVtGJFjYRo5KHk4bCkK4pNVlW7LoqWZFgKZnWK1jdFmxkJBHqddnu5Y3Dw6NOvv67GuhuIf0UOw2jECrEbPvzww0T1ysp2jLEdiJgDAP9iRsEbbrjha16v9246Ourt7RXIfVFWVka8Na6qaqSwsPAf9+/f/4oZmQBwtzMYvOLKnp5naMY6tHz5YtS0EiUYPBnMzS2xIrZEIpESVJS8ZFgKJnU6V92su+G43WJZALLu3bPnpbbLjd1gtVorQ6FQcSQSOWzG4GvXrq1VFOUbuq5XRiKRkKIolPMgjIh+TdMO9fb2PvP73/8+Lj5VtF9ZlqururuvzVXVDwlY9P/pYCmYGWds3XiWwnFlXwruBpOGS2gpNNlH3NVjl8K4G01RxaSAdSm4G8zYuba29ndm6qe7bld9/eYI591z77uvMd19mZWfFLDMdjZdP7UWQES6SUA3Q/mhfKLDL7/8F84vfektM+3Map4UsLI1rhAR99XV1f2rWWOkuj4iXgkAw4yx1MbXJ6EoJdr9aNu2HXMfe2wrY8yThKgJm8YDrEmjdGLpMtmQgxQRH6+rq3soXUaLRy4irgGAr0cikRG/389kWRaoeL3enqKion2MsUPxyEl1HQJW64MPPnHF448/MBZYB2tqZMolSn3G5hNNRAdT7gaK0snPza3QBeHkc88956fNOwVTEKWEDl2jNynQqT/9O1O0Gc75LwRByBMEYWsiRkm2zZIlSyoKCgp+cPLkyRVOpzPi9XptFFEjCAJ3OByqw+F4/I033ngh2X4Sac85//mClpahax566JvA2HBTTc18WRQ5iuJMpqpWXRAcKAg+ifO+aD7RRPox5W6gKB3u9earkuSLAsvlchlROtFClBlykhJ95vDhw5mizewkL7ckSTsSMUqybW688cavdXR0bOvu7raWlJSQE5RARS8eyrKs5efnP3XgwIF/SrafBNs/WHn4cEH19u330Ix1cOXKaqvXG1AV5VaRsWM6YwMi5yoIQn80n2gi/cSzFI4rN1v9WFmyFP5Q07SNmqZFbDYb5SanYy7yX/0ZAP6ZMZa6dDcmnvyFlsJTFRW2iooKjf3udymj/iYFrGzNQSoIwpu1tbX7Tdj7sqlKwGp79NEnK7Zvp5ztGd28XzZGv5gGioh2ou+bPbymPKw9Tz1VU/Kd7zSlMzFKsjNWDWMs5ZcpWiyWnbfccktSlJJUgOTsHTizGWPNqZCXShndO3e6OedFszZv3plKuamSFQ+wxg2maGhouAcAUh6FIori7HXr1mX0Bs2zoHoYACqHh4dHJUmyiaKoKYpCd+f9kTG2L1UPIRE5HTt2rENdL5rz/e8bB+LRa0iiV45kkjJD+ph2N1BSEFEMDezZ09hDwFIU5en58+cbXPBZs2YZN6xSekSPx2O4GxIMBftbRCzWdf0/EzF6KtrcfPPNG7q6urbpui5YLBYbZc6xWCzGzQ2FhYX729ra7mtubs7IhUGiKN5Y7PNdXTEw0FaxdevP/rRiRaWg61YIh09pVmutAHCcyPsoy0omKDPnAWuyHKReVf2zXZbnckkK0NW90RmL8mGWl5cbAQeUIpFK9OreRC7HRMQfki8REY1T+6kuVVVVs0tKSn567NixGnpRyAGsqiqSf85utzNN05r9fv+m48ePZ+r62A0zIpFPVnV3/3bOli0GsHRNmychOjRZXom6/u8Wzq261apngjJzHrDMPsDYpTCVUTpZshTScczPwuHwMkEQApIk0RJI7gLa+5HnPG2XSMbzHMYuhdlEmUkFsNYg4qZ4DGGmjq7rX7vtttsyssyY0TOTdU/v2FHLGZs557vf/Vkm9Riv73g279mo92WpEyJaz2QHYJHgb34zT1PVnNybbz6ajcZIClivvPLKXM45RZykpCBit9vtfi8lwpIQgohFAOBkjB1PQkzKm3Y+9dS9KAg95ffem3X8q7GDnRBYGzdulMvKyvTYbCp0w2pjYyMlOMCx7oYUJAX5ldvtXp/yJ2JCICIuAoAtACB5PB5dEASH1WoNBIPBUy6Xa28mwXb6Jz+5GwWhd/aWLeeicihsjRgJC5ubw5l2McSa2QDWHXfcsZCxiIwafgJEdgJ0YQ6IYGG6NiCDRNelnojQyTJECgQu5gkAfb98/vljse4GukeHkmTQHwqkoAhjs1E6iEhpsp8EAFOcchO4mbBqVVWV48orr3y4paXlG7Isq4FAwEFjoZcrFAphQUHB0/v37yffViZKdXVv77UOVT1OwIpG5eQwNuhT1flgtc4UdF3RGRvOlIvhPGBt2FBbwrnls4xzCm2y6ICnOefMSvca6ZJu93jeHC4slGRdL0ZBKEHO++mG1Vh3AyXMIP8V5Tcgygz5fYjdYLL8GgBKAeAbJtulpPqqVatWCoKwvaWlpXjGjBnERGAELIfDgYqicFEU/+PAgQOPpaQzk0IQ8S6HqlYt6ut7koAVjcoRdd2DFouEgnCTqOtNuiwPZMrFcB6wTI7xXPU0uBuyYSl0RyKRH3POaQkkPxWl06LcnJSU7WnGWNzZjhO163jtYpdCqpNtLoZUAmsDIqbsvjzG2K/dbve3Uv1ALhV5Y4GVzeNK6qswmwc2lbqdTb0opTM4gcYz+Nxz16uInrI77zw4leNLpK+kgEX5OMPhcJ7ZjtetW5e6ywLNdp6G+kP79i0KjYxcV3rXXbRUpi2vZxpUT5vIeIA1bjBFdI9FbgYKsaf0iPRzsptVOecr169f/06qR0X+J1VVb/f7/XPy8/Pp6GUhRRxrmib7/f6hvLw8evApZ272PPPMCnVo6MY5Dzzw2FiOEwUo1DQ16UerqiRyCaR6zNkqzxS7oa2z81RFeflKLggf7d279zgBq7S09Gm6/JGic8jFQPkb6KqTiS7AJGAhYs+tt95qKqx8MiMi4hdUVd3Z3t5elpubG9R13U5c88HBQRQEgZWUlPyioKBg42RyzPyeEvJXDQ7W2Pr7/4KA1bR0qU0QxVusmvZHP+cOwWp1MM5dDGDEKklHrn77bSNxx6VeTAVThDgflkW2iXF4dc8LL/yRgGW32w3aDLkbiCJDmWZaW1uNPJ3jFc75LkEQliHivak08Gc+85nVLpfrO319fQWUySUcDjPOOZdlmQeDQVGW5TcPHTr096nskzF2jYh476JTp15esHXrtqZPf3qVCHCzxet9VrVaC0GSKFuzlQtCSAqFDi86fDhtdOBUjitZWfEsheP2kSjRL40zFnnNt+q6/leRCMUw2MhdQEsiPUz6+Sxj7PVkjRbbnmaslX19n4hdCrPZDZDKsU8kK2PASscea6qMNrafifZYmdIp0/0mBazdu3fb8vLyiNRvqnzxi1+ky4UumTL0/PPVQY/nurJ77tk5/VV45rEmBaxLBhlJDmSq/FhJqjmlzf8PpAPT8GA7MOQAAAAASUVORK5CYII=" | |
}, | |
"dataset": [ | |
{ | |
"key": "__0__", | |
"name": "Category", | |
"description": "Category column for each bar", | |
"type": "text", | |
"kind": "column" | |
}, | |
{ | |
"key": "__1__", | |
"name": "Value", | |
"description": "Main bar value", | |
"type": "numeric", | |
"kind": "measure" | |
}, | |
{ | |
"key": "__2__", | |
"name": "Target", | |
"description": "Target value", | |
"type": "numeric", | |
"kind": "measure" | |
}, | |
{ | |
"key": "__3__", | |
"name": "Gap", | |
"description": "Gap to target", | |
"type": "numeric", | |
"kind": "measure" | |
} | |
] | |
}, | |
"config": { | |
"view": {"stroke": "transparent"}, | |
"font": "Segoe UI", | |
"axis": { | |
"ticks": false, | |
"grid": false, | |
"domain": false, | |
"title": "", | |
"labelColor": "#605E5C", | |
"labelFontSize": 12, | |
"titleFont": "wf_standard-font, helvetica, arial, sans-serif", | |
"titleColor": "#252423", | |
"titleFontSize": 16, | |
"titleFontWeight": "normal", | |
"labelPadding": 10 | |
}, | |
"tick": { | |
"stroke": "white", | |
"strokeWidth": 1, | |
"thickness": 3 | |
}, | |
"point": { | |
"filled": true, | |
"size": 50, | |
"opacity": 1 | |
}, | |
"style": { | |
"target": {"color": "#cd3838"}, | |
"value_label": { | |
"color": "white", | |
"align": "left", | |
"dx": 5 | |
} | |
} | |
}, | |
"data": {"name": "dataset"}, | |
"height": {"step": 30}, | |
"encoding": { | |
"x": { | |
"type": "quantitative", | |
"axis": null | |
}, | |
"y": { | |
"field": "__0__", | |
"sort": { | |
"field": "__1__", | |
"op": "sum", | |
"order": "descending" | |
} | |
} | |
}, | |
"params": [ | |
{ | |
"name": "bar_color", | |
"value": "#aaa" | |
} | |
], | |
"transform": [ | |
{ | |
"calculate": "datum['__3__'] < 0", | |
"as": "gap_is_negative" | |
}, | |
{ | |
"calculate": "datum['gap_is_negative'] ? '#fff' : bar_color", | |
"as": "gap_color" | |
}, | |
{ | |
"calculate": "datum['gap_is_negative'] ? bar_color : '#fff'", | |
"as": "gap_color_inverse" | |
}, | |
{ | |
"calculate": "datum['__2__'] - (datum['__3__'] / 2)", | |
"as": "gap_label_x" | |
} | |
], | |
"layer": [ | |
{ | |
"description": "Main value bar", | |
"mark": { | |
"type": "bar", | |
"color": {"expr": "bar_color"}, | |
"height": {"band": 0.8} | |
}, | |
"encoding": { | |
"x": {"field": "__1__"} | |
} | |
}, | |
{ | |
"description": "Target tick", | |
"mark": { | |
"type": "tick", | |
"style": ["target"], | |
"height": { | |
"expr": "bandwidth('y')" | |
} | |
}, | |
"encoding": { | |
"x": {"field": "__2__"} | |
} | |
}, | |
{ | |
"description": "Value label", | |
"mark": { | |
"type": "text", | |
"style": ["value_label"] | |
}, | |
"encoding": { | |
"x": {"datum": 0}, | |
"text": { | |
"field": "__1__", | |
"format": "#,###,", | |
"formatType": "pbiFormat" | |
} | |
} | |
}, | |
{ | |
"description": "Target label", | |
"layer": [ | |
{ | |
"description": "Target label foreground", | |
"mark": { | |
"type": "text", | |
"style": ["target"], | |
"align": { | |
"expr": "datum['gap_is_negative'] ? 'right' : 'left'" | |
}, | |
"dx": { | |
"expr": "datum['gap_is_negative'] ? -10 : 10" | |
} | |
} | |
} | |
], | |
"encoding": { | |
"x": {"field": "__2__"}, | |
"text": { | |
"field": "__2__", | |
"format": "#,###,", | |
"formatType": "pbiFormat" | |
} | |
} | |
}, | |
{ | |
"description": "Gap arrow main layer", | |
"encoding": { | |
"color": { | |
"value": { | |
"expr": "datum['gap_color']" | |
} | |
} | |
}, | |
"layer": [ | |
{ | |
"description": "Gap arrow body", | |
"mark": {"type": "rule"}, | |
"encoding": { | |
"x": {"field": "__1__"}, | |
"x2": {"field": "__2__"} | |
} | |
}, | |
{ | |
"description": "Gap arrow head (left)", | |
"mark": { | |
"type": "point", | |
"shape": "triangle-left", | |
"xOffset": 3 | |
}, | |
"encoding": { | |
"x": { | |
"value": { | |
"expr": "scale('x', datum['gap_is_negative'] ? datum['__2__'] : datum['__1__'])" | |
} | |
} | |
} | |
}, | |
{ | |
"description": "Gap arrow head (right)", | |
"mark": { | |
"type": "point", | |
"shape": "triangle-right", | |
"xOffset": -3 | |
}, | |
"encoding": { | |
"x": { | |
"value": { | |
"expr": "scale('x', datum['gap_is_negative'] ? datum['__1__'] : datum['__2__'])" | |
} | |
} | |
} | |
} | |
] | |
}, | |
{ | |
"description": "Gap label main layer", | |
"encoding": { | |
"x": {"field": "gap_label_x"}, | |
"text": { | |
"field": "__3__", | |
"format": "#,###,;#,##,", | |
"formatType": "pbiFormat" | |
} | |
}, | |
"layer": [ | |
{ | |
"description": "Gap label halo (background)", | |
"mark": { | |
"type": "text", | |
"stroke": { | |
"expr": "datum['gap_color_inverse']" | |
}, | |
"strokeWidth": 4 | |
} | |
}, | |
{ | |
"description": "Gap label halo (background)", | |
"mark": { | |
"type": "text", | |
"color": { | |
"expr": "datum['gap_color']" | |
} | |
} | |
} | |
] | |
} | |
] | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment