Skip to main content
This site and Lume package is currently under development and may not be stable.

Bar chart

Series arranged in categories but with data displayed as bars.

Our bar chart component currently renders horizontal bar charts. By limiting to horizontal bars it reduces some of the issues of label sizes and allows us to expand the chart vertically - it would be harder to expand horizontally without shrinking the size of the bars/labels. Javascript adds tooltips and can make legend items interactive. Hovering over a series in a legend will fade the other series and shift the highlighted series to the left to allow easier comparison.

Usage

To use this component in a Nunjucks template you would add the following (assumes you've loaded OI Lume Viz into componentNamespace: 'oi'):

{% comp 'oi.chart.bar', { "config": config } %}{% endcomp %}

where config is replaced by an object that contains some or all of these variables:

  • data - Either a reference to a CSV file in the Lume site or an array of rows with named attributes
  • columns - As with many of the visualisation types you can optionally add virtual columns.
  • colours - Define some visualisation-specific named colours.
  • width - Set a specific width for the visualisation.
  • height - Set a specific height for the visualisation.
  • axis - Define the x (horizontal) axis.
  • legend - Define the legend.
  • category - The title of the column that contains the categories (vertical groups).
  • series - An ordered array of series. Each one is of the form:
    • title - The display name of the series.
    • value - The title of the column to use for the value of the bar.
    • colour - The hex code to use to colour this series.
    • tooltip - Either a string, template string, or the column heading to use to build a tooltip.
  • gap - Add spacing between the bars as a fraction of the bar width. The default is 0.
  • stacked - (boolean) This lets us stack the series within each category. The default is false.
  • percent - (boolean) Used with stacked to build 100% width stacked bar charts. This creates virtual columns in your data with the same name as the original columns but with _percent appended. Note that the normalised columns will be created before any virtual columns that you have created. The default is false.
  • attribution - Add a line of attribution text under the visualisation.

Examples

  1. One series - minimal config with auto scaling and auto-ticks
  2. One series - defined scaling and ticks
  3. Two series - customised tooltips
  4. Multi series - customised colours
  5. Stacked bar chart - auto scaling
  6. Stacked bar chart - defined scaling
  7. Stacked bar chart - 100% chart
  8. Data object

1. One series - minimal config with auto scaling and auto-ticks§

Embeddable version

If you have regularly updated "live" data you may not know the scale that will be needed for the values in advance. In that case you can set a axis → x → tick → spacing and let the chart calculate an automatic range and tick marks.

0.015.022.530.037.545.07.5Fourth categoryThird categorySecond categoryFirst categorySeries One First category: 20Series One Second category: 10Series One Third category: 43Series One Fourth category: 15

This example was made with config:

YAML
data:
  - category: First category
    series1: 20
  - category: Second category
    series1: 10
  - category: Third category
    series1: 43
  - category: Fourth category
    series1: 15
category: category
series:
  - title: Series One
    value: series1
axis:
  x:
    tick:
      spacing: 7.5
JSON
{
	"data": [{
			"category": "First category",
			"series1": 20
		},{
			"category": "Second category",
			"series1": 10
		},{
			"category": "Third category",
			"series1": 43
		},{
			"category": "Fourth category",
			"series1": 15
		}],
	"category": "category",
	"series": [{
			"title": "Series One",
			"value": "series1"
		}],
	"axis": {
		"x": {
			"tick": {
				"spacing": 7.5
			}
		}
	}
}

2. One series - defined scaling and ticks§

Embeddable version

A simple one series bar chart showing four categories. The x-axis (value) can use a customised axis → x → min/axis → x → max and you can specify which tick marks are shown and what their labels are using axis → x → ticks. This gives the flexibility of very customised labels or no labels for ticks.

Series One
10%20%30%40%50%Fourth categoryThird categorySecond categoryFirst categorySeries One First category: 20Series One Second category: 10Series One Third category: 45Series One Fourth category: 15

This example was made with config:

YAML
data:
  - category: First category
    series1: 20
  - category: Second category
    series1: 10
  - category: Third category
    series1: 45
  - category: Fourth category
    series1: 15
legend:
  show: true
  position: top
axis:
  x:
    min: 0
    max: 60
    grid:
      stroke-dasharray: 6 2
      stroke-width: 1
    ticks:
      - value: 10
        label: 10%
      - value: 20
        label: 20%
      - value: 30
        label: 30%
      - value: 40
        label: 40%
      - value: 50
        label: 50%
  'y':
    grid:
      stroke-width: 0.5
category: category
series:
  - title: Series One
    value: series1
JSON
{
	"data": [{
			"category": "First category",
			"series1": 20
		},{
			"category": "Second category",
			"series1": 10
		},{
			"category": "Third category",
			"series1": 45
		},{
			"category": "Fourth category",
			"series1": 15
		}],
	"legend": {
		"show": true,
		"position": "top"
	},
	"axis": {
		"x": {
			"min": 0,
			"max": 60,
			"grid": {
				"stroke-dasharray": "6 2",
				"stroke-width": 1
			},
			"ticks": [{
					"value": 10,
					"label": "10%"
				},{
					"value": 20,
					"label": "20%"
				},{
					"value": 30,
					"label": "30%"
				},{
					"value": 40,
					"label": "40%"
				},{
					"value": 50,
					"label": "50%"
				}]
		},
		"y": {
			"grid": {
				"stroke-width": 0.5
			}
		}
	},
	"category": "category",
	"series": [{
			"title": "Series One",
			"value": "series1"
		}]
}

3. Two series - customised tooltips§

Embeddable version

Add two series to a horizontal bar chart. Each series gets its own colour. Javascript is used to make the legend interactive (hovering over a series will highlight that series). We can set a tooltip for each series which can either refer to a specific column/virtual column in the data or be a string template.

Aspect 2
Aspect 1
20%30%40%50%Ethnic Group CEthnic Group BEthnic Group AAspect 1
Ethnic Group A: 34%
Aspect 1
Ethnic Group B: 45%
Aspect 1
Ethnic Group C: 36%
Aspect 2
Ethnic Group A: 23%
Aspect 2
Ethnic Group B: 35%
Aspect 2
Ethnic Group C: 10%

This example was made with config:

YAML
data:
  - Ethnic group: Ethnic Group A
    Aspect 1 (%): 34
    Aspect 2 (%): 23
  - Ethnic group: Ethnic Group B
    Aspect 1 (%): 45
    Aspect 2 (%): 35
  - Ethnic group: Ethnic Group C
    Aspect 1 (%): 36
    Aspect 2 (%): 10
legend:
  show: true
  position: top
axis:
  x:
    min: 15
    max: 58
    grid:
      stroke-dasharray: 6 2
      stroke-width: 1
    ticks:
      - value: 20
        label: 20%
      - value: 30
        label: 30%
      - value: 40
        label: 40%
      - value: 50
        label: 50%
  'y':
    grid:
      stroke-width: 0.5
category: Ethnic group
series:
  - title: Aspect 1
    value: Aspect 1 (%)
    tooltip: 'Aspect 1<br />{{ Ethnic group}}: {{ Aspect 1 (%) }}%'
  - title: Aspect 2
    value: Aspect 2 (%)
    tooltip: 'Aspect 2<br />{{ Ethnic group}}: {{ Aspect 2 (%) }}%'
JSON
{
	"data": [{
			"Ethnic group": "Ethnic Group A",
			"Aspect 1 (%)": 34,
			"Aspect 2 (%)": 23
		},{
			"Ethnic group": "Ethnic Group B",
			"Aspect 1 (%)": 45,
			"Aspect 2 (%)": 35
		},{
			"Ethnic group": "Ethnic Group C",
			"Aspect 1 (%)": 36,
			"Aspect 2 (%)": 10
		}],
	"legend": {
		"show": true,
		"position": "top"
	},
	"axis": {
		"x": {
			"min": 15,
			"max": 58,
			"grid": {
				"stroke-dasharray": "6 2",
				"stroke-width": 1
			},
			"ticks": [{
					"value": 20,
					"label": "20%"
				},{
					"value": 30,
					"label": "30%"
				},{
					"value": 40,
					"label": "40%"
				},{
					"value": 50,
					"label": "50%"
				}]
		},
		"y": {
			"grid": {
				"stroke-width": 0.5
			}
		}
	},
	"category": "Ethnic group",
	"series": [{
			"title": "Aspect 1",
			"value": "Aspect 1 (%)",
			"tooltip": "Aspect 1<br />{{ Ethnic group}}: {{ Aspect 1 (%) }}%"
		},{
			"title": "Aspect 2",
			"value": "Aspect 2 (%)",
			"tooltip": "Aspect 2<br />{{ Ethnic group}}: {{ Aspect 2 (%) }}%"
		}]
}

4. Multi series - customised colours§

Embeddable version

Add spacing between series' bars as a fraction of the bar width. Explicitly set the colours of each series (as either a hex colour, an RGB colour or a named CSS colour).

University
College
School
10%20%30%40%50%Reason 3Reason 2Reason 1Reason 1
School: 10%
Reason 2
School: 10%
Reason 3
School: 10%
Reason 1
College: 15%
Reason 2
College: 15%
Reason 3
College: 15%
Reason 1
University: 20%
Reason 2
University: 20%
Reason 3
University: 20%

This example was made with config:

YAML
data:
  - Reason: Reason 1
    School: 10
    College: 15
    University: 20
  - Reason: Reason 2
    School: 10
    College: 15
    University: 20
  - Reason: Reason 3
    School: 10
    College: 15
    University: 20
summary: Employers were not asked separately about each type of placement
legend:
  show: true
  position: top
axis:
  x:
    min: 0
    max: 60
    grid:
      stroke-dasharray: 6 2
      stroke-width: 1
    ticks:
      - value: 10
        label: 10%
      - value: 20
        label: 20%
      - value: 30
        label: 30%
      - value: 40
        label: 40%
      - value: 50
        label: 50%
  'y':
    grid:
      stroke-width: 0.5
gap: 0.2
category: Reason
series:
  - title: School
    value: School
    colour: '#E52E36'
    tooltip: '{{ Reason }}<br />School: {{ School }}%'
  - title: College
    value: College
    colour: '#F7AB3D'
    tooltip: '{{ Reason }}<br />College: {{ College }}%'
  - title: University
    value: University
    colour: '#69C2C9'
    tooltip: '{{ Reason }}<br />University: {{ University }}%'
JSON
{
	"data": [{
			"Reason": "Reason 1",
			"School": 10,
			"College": 15,
			"University": 20
		},{
			"Reason": "Reason 2",
			"School": 10,
			"College": 15,
			"University": 20
		},{
			"Reason": "Reason 3",
			"School": 10,
			"College": 15,
			"University": 20
		}],
	"summary": "Employers were not asked separately about each type of placement",
	"legend": {
		"show": true,
		"position": "top"
	},
	"axis": {
		"x": {
			"min": 0,
			"max": 60,
			"grid": {
				"stroke-dasharray": "6 2",
				"stroke-width": 1
			},
			"ticks": [{
					"value": 10,
					"label": "10%"
				},{
					"value": 20,
					"label": "20%"
				},{
					"value": 30,
					"label": "30%"
				},{
					"value": 40,
					"label": "40%"
				},{
					"value": 50,
					"label": "50%"
				}]
		},
		"y": {
			"grid": {
				"stroke-width": 0.5
			}
		}
	},
	"gap": 0.2,
	"category": "Reason",
	"series": [{
			"title": "School",
			"value": "School",
			"colour": "#E52E36",
			"tooltip": "{{ Reason }}<br />School: {{ School }}%"
		},{
			"title": "College",
			"value": "College",
			"colour": "#F7AB3D",
			"tooltip": "{{ Reason }}<br />College: {{ College }}%"
		},{
			"title": "University",
			"value": "University",
			"colour": "#69C2C9",
			"tooltip": "{{ Reason }}<br />University: {{ University }}%"
		}]
}

5. Stacked bar chart - auto scaling§

Embeddable version

Rather than side-by-side bars, sometimes we need to stack bars. As stacked-bar charts don't do a good job of allowing you to compare any series other than the first, we use Javascript to make the legend interactive; hovering over a series will shift this series to the left of the chart to make comparison across categories easier.

25+
19-24
Under 19
0100200300400500202020192018Under 19 2018: 150Under 19 2019: 190Under 19 2020: 30019-24 2018: 1519-24 2019: 3519-24 2020: 6525+ 2018: 2025+ 2019: 4525+ 2020: 55

This example was made with config:

YAML
colours:
  test: '#999000'
data:
  - Year: 2018
    u19: 150
    19-24: 15
    25+: 20
  - Year: 2019
    u19: 190
    19-24: 35
    25+: 45
  - Year: 2020
    u19: 300
    19-24: 65
    25+: 55
stacked: true
legend:
  show: true
  position: top
axis:
  x:
    grid:
      stroke-dasharray: 6 2
      stroke-width: 1
    tick:
      spacing: 100
  'y':
    grid:
      stroke-width: 0.5
category: Year
series:
  - title: Under 19
    value: u19
    colour: '#69C2C9'
  - title: 19-24
    value: 19-24
    colour: '#7D2248'
  - title: 25+
    value: 25+
    colour: '#4A783C'
JSON
{
	"colours": {
		"test": "#999000"
	},
	"data": [{
			"Year": 2018,
			"u19": 150,
			"19-24": 15,
			"25+": 20
		},{
			"Year": 2019,
			"u19": 190,
			"19-24": 35,
			"25+": 45
		},{
			"Year": 2020,
			"u19": 300,
			"19-24": 65,
			"25+": 55
		}],
	"stacked": true,
	"legend": {
		"show": true,
		"position": "top"
	},
	"axis": {
		"x": {
			"grid": {
				"stroke-dasharray": "6 2",
				"stroke-width": 1
			},
			"tick": {
				"spacing": 100
			}
		},
		"y": {
			"grid": {
				"stroke-width": 0.5
			}
		}
	},
	"category": "Year",
	"series": [{
			"title": "Under 19",
			"value": "u19",
			"colour": "#69C2C9"
		},{
			"title": "19-24",
			"value": "19-24",
			"colour": "#7D2248"
		},{
			"title": "25+",
			"value": "25+",
			"colour": "#4A783C"
		}]
}

6. Stacked bar chart - defined scaling§

Embeddable version

As for the previous example but we'll explicitly define the axis → x.

25+
19-24
Under 19
100200300400500600202020192018Under 19 2018: 150Under 19 2019: 190Under 19 2020: 30019-24 2018: 1519-24 2019: 3519-24 2020: 6525+ 2018: 2025+ 2019: 4525+ 2020: 55

This example was made with config:

YAML
data:
  - Year: 2018
    u19: 150
    19-24: 15
    25+: 20
  - Year: 2019
    u19: 190
    19-24: 35
    25+: 45
  - Year: 2020
    u19: 300
    19-24: 65
    25+: 55
stacked: true
legend:
  show: true
  position: top
axis:
  x:
    min: 0
    max: 600
    grid:
      stroke-dasharray: 6 2
      stroke-width: 1
    ticks:
      - value: 100
        label: '100'
      - value: 200
        label: '200'
      - value: 300
        label: '300'
      - value: 400
        label: '400'
      - value: 500
        label: '500'
      - value: 600
        label: '600'
  'y':
    grid:
      stroke-width: 0.5
category: Year
series:
  - title: Under 19
    value: u19
    colour: '#69C2C9'
  - title: 19-24
    value: 19-24
    colour: '#7D2248'
  - title: 25+
    value: 25+
    colour: '#4A783C'
JSON
{
	"data": [{
			"Year": 2018,
			"u19": 150,
			"19-24": 15,
			"25+": 20
		},{
			"Year": 2019,
			"u19": 190,
			"19-24": 35,
			"25+": 45
		},{
			"Year": 2020,
			"u19": 300,
			"19-24": 65,
			"25+": 55
		}],
	"stacked": true,
	"legend": {
		"show": true,
		"position": "top"
	},
	"axis": {
		"x": {
			"min": 0,
			"max": 600,
			"grid": {
				"stroke-dasharray": "6 2",
				"stroke-width": 1
			},
			"ticks": [{
					"value": 100,
					"label": "100"
				},{
					"value": 200,
					"label": "200"
				},{
					"value": 300,
					"label": "300"
				},{
					"value": 400,
					"label": "400"
				},{
					"value": 500,
					"label": "500"
				},{
					"value": 600,
					"label": "600"
				}]
		},
		"y": {
			"grid": {
				"stroke-width": 0.5
			}
		}
	},
	"category": "Year",
	"series": [{
			"title": "Under 19",
			"value": "u19",
			"colour": "#69C2C9"
		},{
			"title": "19-24",
			"value": "19-24",
			"colour": "#7D2248"
		},{
			"title": "25+",
			"value": "25+",
			"colour": "#4A783C"
		}]
}

7. Stacked bar chart - 100% chart§

Embeddable version

Sometimes you want to show a part-to-whole relationship for each category i.e. you want the cumulative category bar to take up 100% of the chart width. This lets you see the relative contributions of each series to a category.

One way to do this would be to create new columns in your data - one for each series - that contain the percentage contribution of that series' value to the total for the category. If you don't have the ability to control the input data file we can create those columns for you with the percent: true option. This will create a new virtual column of data for each series. These new columns will have the same name as the original columns but with _percent appended. This lets you refer to the original values and the normalised values in any tooltips that you create. Note that the normalised columns will be created before any virtual columns that you have created.

In this example we will define the tooltip of the final series (25+) so that you can see how you would be able to include both the percentage and original values. The tooltips for the first two series are auto-generated.

25+
19-24
Under 19
10020406080202020192018Under 19 2018: 81.08%Under 19 2019: 70.37%Under 19 2020: 71.43%19-24 2018: 8.11%19-24 2019: 12.96%19-24 2020: 15.48%25+ 2018: 10.8% (20) 25+ 2019: 16.7% (45) 25+ 2020: 13.1% (55)

This example was made with config:

YAML
data:
  - Year: 2018
    u19: 150
    19-24: 15
    25+: 20
  - Year: 2019
    u19: 190
    19-24: 35
    25+: 45
  - Year: 2020
    u19: 300
    19-24: 65
    25+: 55
stacked: true
percent: true
legend:
  show: true
  position: top
axis:
  x:
    grid:
      stroke-dasharray: 6 2
      stroke-width: 1
    ticks:
      - value: 20
        label: '20'
      - value: 40
        label: '40'
      - value: 60
        label: '60'
      - value: 80
        label: '80'
      - value: 100
        label: '100'
  'y':
    grid:
      stroke-width: 0.5
category: Year
series:
  - title: Under 19
    value: u19
    colour: '#69C2C9'
  - title: 19-24
    value: 19-24
    colour: '#7D2248'
  - title: 25+
    value: 25+
    tooltip: |
      25+
      {{ Year }}: {{ 25+_percent | toFixed(1) }}% ({{ 25+ }})
    colour: '#4A783C'
JSON
{
	"data": [{
			"Year": 2018,
			"u19": 150,
			"19-24": 15,
			"25+": 20
		},{
			"Year": 2019,
			"u19": 190,
			"19-24": 35,
			"25+": 45
		},{
			"Year": 2020,
			"u19": 300,
			"19-24": 65,
			"25+": 55
		}],
	"stacked": true,
	"percent": true,
	"legend": {
		"show": true,
		"position": "top"
	},
	"axis": {
		"x": {
			"grid": {
				"stroke-dasharray": "6 2",
				"stroke-width": 1
			},
			"ticks": [{
					"value": 20,
					"label": "20"
				},{
					"value": 40,
					"label": "40"
				},{
					"value": 60,
					"label": "60"
				},{
					"value": 80,
					"label": "80"
				},{
					"value": 100,
					"label": "100"
				}]
		},
		"y": {
			"grid": {
				"stroke-width": 0.5
			}
		}
	},
	"category": "Year",
	"series": [{
			"title": "Under 19",
			"value": "u19",
			"colour": "#69C2C9"
		},{
			"title": "19-24",
			"value": "19-24",
			"colour": "#7D2248"
		},{
			"title": "25+",
			"value": "25+",
			"tooltip": "25+\n{{ Year }}: {{ 25+_percent | toFixed(1) }}% ({{ 25+ }})\n",
			"colour": "#4A783C"
		}]
}

8. Data object§

Embeddable version

Get the data for the bar chart from an object

Test values
010203040Third categorySecond categoryFirst categoryTest values First category: 10Test values Second category: 33Test values Third category: 25

This example was made with config:

YAML
data: test.data.bar
category: category
series:
  - title: Test values
    value: value
stacked: false
legend:
  show: true
  position: top
axis:
  x:
    tick:
      spacing: 10
  'y':
    grid:
      stroke-width: 0.5
JSON
{
	"data": "test.data.bar",
	"category": "category",
	"series": [{
			"title": "Test values",
			"value": "value"
		}],
	"stacked": false,
	"legend": {
		"show": true,
		"position": "top"
	},
	"axis": {
		"x": {
			"tick": {
				"spacing": 10
			}
		},
		"y": {
			"grid": {
				"stroke-width": 0.5
			}
		}
	}
}