I have made a bar chart which have two columns per category. These columns can have positive or negative values. My data values would sometimes have extremely large and small range or gap which results to small values not being visible enough. I have added a strokeWidth
that extremely small values will have a minimum pixel and would still be visible in the graph.
After adding the strokeWidth
, it messes with the columns axis starting position from the zero line. Negative items now displays above the zero line when it should be starting from there.
I think it is related to this: https://github.com/vega/vega/pull/3487
Try setting an offset on your y2:
{
"$schema": "https://vega.github.io/schema/vega/v5.json",
"width": 700,
"height": 370,
"autosize": {"type": "fit", "contains": "padding"},
"padding": {"bottom": 2, "right": 9, "left": 5},
"config": {
"axis": {
"labelFont": "HelveticaNeueLTW01-55Roman",
"titleFont": "HelveticaNeueLTW01-55Roman"
}
},
"data": [
{
"name": "capital_flows",
"values": [
{"label": "2012", "capital_inflow": 208.91, "capital_outflow": -500},
{"label": "2013", "capital_inflow": 115.61, "capital_outflow": -458.76},
{"label": "2014", "capital_inflow": 135.7, "capital_outflow": -335.23},
{"label": "2015", "capital_inflow": 148.75, "capital_outflow": -83.61},
{"label": "2016", "capital_inflow": 152.57, "capital_outflow": 0.36},
{"label": "2017", "capital_inflow": 198.23, "capital_outflow": 0.29},
{"label": "2018", "capital_inflow": 911.81, "capital_outflow": 0.58},
{"label": "2019", "capital_inflow": 5342.44, "capital_outflow": 14.48},
{"label": "2020", "capital_inflow": 4664.46, "capital_outflow": 11.51},
{"label": "2021", "capital_inflow": 3800.92, "capital_outflow": 7.54},
{"label": "2022", "capital_inflow": 6633, "capital_outflow": 12.04},
{"label": "2023", "capital_inflow": 7381.93, "capital_outflow": 5.31},
{"label": "2024", "capital_inflow": 3612.31, "capital_outflow": 3.7}
],
"transform": [
{"type": "formula", "expr": "split(datum.label, ' ')", "as": "label"}
]
},
{
"name": "parsed",
"source": ["capital_flows"],
"transform": [
{
"type": "aggregate",
"fields": [
"capital_inflow",
"capital_inflow",
"capital_outflow",
"capital_outflow"
],
"ops": ["min", "max", "min", "max"],
"as": ["min_value1", "max_value1", "min_value2", "max_value2"]
},
{
"type": "formula",
"expr": "datum.max_value1 == 0 && datum.max_value2 == 0 ? 1 : datum.max_value1 > datum.max_value2 ? abs(datum.max_value1) : abs(datum.max_value2)",
"as": "mergedMax"
},
{
"type": "formula",
"expr": "datum.min_value1 == 0 && datum.min_value2 == 0 ? -1 : datum.min_value1 < datum.min_value2 ? abs(datum.min_value1) : abs(datum.min_value2)",
"as": "mergedMin"
},
{
"type": "formula",
"expr": "datum.mergedMax > datum.mergedMin ? datum.mergedMax : datum.mergedMin",
"as": "max"
},
{"type": "formula", "expr": "-(datum.max)", "as": "min"}
]
}
],
"scales": [
{
"name": "x",
"type": "band",
"range": "width",
"domain": {"data": "capital_flows", "field": "label"}
},
{
"name": "y",
"type": "linear",
"range": "height",
"nice": true,
"zero": false,
"domain": {"data": "parsed", "field": "limit"},
"domainMin": {"signal": "pluck(data('parsed'), 'min')"},
"domainMax": {"signal": "pluck(data('parsed'), 'max')"}
}
],
"axes": [
{
"orient": "bottom",
"scale": "x",
"zindex": 1,
"labelFontSize": 12,
"labelColor": "#85868C",
"labelAlign": "center",
"labelLineHeight": 16.8,
"labelFontWeight": "normal",
"labelPadding": 8,
"labelOpacity": 1,
"domain": false,
"domainColor": "#e5e5e5",
"domainWidth": 1,
"ticks": false
},
{
"orient": "left",
"scale": "y",
"zindex": 0,
"labelFontSize": 12,
"labelColor": "#85868C",
"labelLineHeight": 16.8,
"labelFontWeight": "normal",
"labelPadding": 8,
"labelOpacity": 1,
"domain": false,
"domainColor": "#e5e5e5",
"grid": true,
"gridOpacity": 0.5,
"ticks": false,
"tickCount": {"signal": "pluck(data('parsed'), 'max') < 1000 ? 4 : 6"},
"gridDash": {"signal": "datum.value == 0 ? [0,0] : [4,4]"},
"encode": {
"labels": {
"update": {
"text": {
"signal": "if(abs(datum.value) >= 1e9, format(datum.value/1e9, '$,.1~f') + 'B', if(abs(datum.value) >= 1e6, format(datum.value/1e6, '$,.1~f') + 'M', if(abs(datum.value) >= 1e3, format(datum.value/1e3, '$,.1~f') + 'K', format(datum.value, '$,.2~f'))))"
}
}
}
}
}
],
"marks": [
{
"name": "inflow",
"type": "rect",
"from": {"data": "capital_flows"},
"encode": {
"enter": {
"xc": {"scale": "x", "field": "label", "band": 0.5},
"width": {"value": 16},
"y": {"scale": "y", "field": "capital_inflow"},
"y2": {"scale": "y", "value": 0},
"fill": {"value": "#68c487"},
"cornerRadiusTopLeft": {
"signal": "datum.capital_inflow > 0 ? '1' : '0'"
},
"cornerRadiusTopRight": {
"signal": "datum.capital_inflow > 0 ? '1' : '0'"
},
"cornerRadiusBottomLeft": {
"signal": "datum.capital_inflow > 0 ? '0' : '1'"
},
"cornerRadiusBottomRight": {
"signal": "datum.capital_inflow > 0 ? '0' : '1'"
},
"stroke": {"signal": "datum.capital_inflow !== 0 ? '#68c487': null"}
}
}
},
{
"name": "outflow",
"type": "rect",
"from": {"data": "capital_flows"},
"encode": {
"enter": {
"xc": {"scale": "x", "field": "label", "band": 0.5, "offset": 19},
"width": {"value": 16},
"y": {"scale": "y", "field": "capital_outflow"},
"y2": {"scale": "y", "value": 0, "offset":1.5},
"fill": {"value": "#FFB066"},
"cornerRadiusTopLeft": {
"signal": "datum.capital_outflow > 0 ? '1' : '0'"
},
"cornerRadiusTopRight": {
"signal": "datum.capital_outflow > 0 ? '1' : '0'"
},
"cornerRadiusBottomLeft": {
"signal": "datum.capital_outflow > 0 ? '0' : '1'"
},
"cornerRadiusBottomRight": {
"signal": "datum.capital_outflow > 0 ? '0' : '1'"
},
"stroke": {"signal": "datum.capital_outflow !== 0 ? '#FFB066': null"},
"strokeWidth": {"value": 1.5}
}
}
}
]
}