Line chart Since 0.1.0
Multiple series shown as a line graph.
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.line', { "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 thex
(horizontal) axis.legend
- Define the legend.series
- An ordered array of series. Each one is of the form:title
- The display name of the series.x
- The title of the column to use for the horizontal axis value.y
- The title of the column to use for the vertical axis value.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.points
- Properties of the points:size
- The size of the point.marker
- One ofcircle
,triangle
,square
,diamond
,pentagon
,hexagon
,octagon
,line
, orcross
.rotate
- How much to rotate the marker around its centre by, in degrees.
line
- Properties of the line that joins the points:curvature
- The amount of curvature to apply to the line (1
= maximum,0
= none.stroke-dasharray
- Define a stroke-dasharray for the stroke e.g. "6 2".stroke-width
- Define a width for the stroke.stroke-linecap
- The stroke-linecap
where
- Limit the rows to include
attribution
- Add a line of attribution text under the visualisation.
Examples
- Basic
- Auto-generated grid
- Explicitly defined grid
- Category-based data
- Custom icons
- Gaps in series
- Limiting a series to specific rows
1. Basic§
This is a basic line chart with one data series showing unemployment over time for 16-17 year olds (data from the ONS's A01: Summary of labour market statistics). The graph is auto-scaled to the data using axis → x → tick→ pacing
and axis → y → tick→ spacing
. The tick marks for each axis
are defined using those same properties and styled with axis → x → grid
. To calculate the x
values we take the Date
column (e.g. "Mar-May 1992"), extract the end of the month range, and then convert the result to a decimal year.
This example was made with config
:
data: test.data.unemploymentByAge
columns:
- name: decimal_year
template: '{{ Date | strptime("-%b %Y") | decimalYear() }}'
series:
- title: 16-17
x: decimal_year
y: 16-17→rate (%)1
colour: '#e52e36'
{
"data": "test.data.unemploymentByAge",
"columns": [{
"name": "decimal_year",
"template": "{{ Date | strptime(\"-%b %Y\") | decimalYear() }}"
}],
"series": [{
"title": "16-17",
"x": "decimal_year",
"y": "16-17→rate (%)1",
"colour": "#e52e36"
}]
}
2. Auto-generated grid§
This is a basic line chart showing the same data as above. In this example we have auto-scaled each axis to the data using axis → x → tick → spacing
and axis → y → tick → spacing
. The tick → spacing
values are used to auto generate tick marks which are styled with axis → x → grid
and axis → y → grid
.
This example was made with config
:
data: test.data.unemploymentByAge
columns:
- name: decimal_year
template: '{{ Date | strptime("-%b %Y") | decimalYear() }}'
axis:
x:
grid:
show: true
tick:
spacing: 5
'y':
grid:
show: true
tick:
spacing: 5
series:
- title: 16-17
x: decimal_year
y: 16-17→rate (%)1
colour: '#e52e36'
{
"data": "test.data.unemploymentByAge",
"columns": [{
"name": "decimal_year",
"template": "{{ Date | strptime(\"-%b %Y\") | decimalYear() }}"
}],
"axis": {
"x": {
"grid": {
"show": true
},
"tick": {
"spacing": 5
}
},
"y": {
"grid": {
"show": true
},
"tick": {
"spacing": 5
}
}
},
"series": [{
"title": "16-17",
"x": "decimal_year",
"y": "16-17→rate (%)1",
"colour": "#e52e36"
}]
}
3. Explicitly defined grid§
This more complicated chart shows four different age groups from A01: Summary of labour market statistics. We define titles for each axis. The x-axis range is explicitly limited to the years 2000
to 2022.5
with tick marks set every 2 years but only showing labels on the decades. The tickSize
is defined per tick
. The vertical lines (associated with ticks on the x-axis) have stroke-dasharray
set to make them dashed and a tick → size
set for the axis
rather than for each tick. We can customise the tooltip
for each series
by providing a column/virtual column in the data or a string template. We also create an interactive legend.
This example was made with config
:
data: test.data.unemploymentByAge
columns:
- name: decimal_year
template: '{{ Date | strptime("-%b %Y") | decimalYear() }}'
legend:
show: true
axis:
x:
title:
label: Year
grid:
stroke-dasharray: 6 2
stroke-width: 1
ticks:
- value: 2000
grid: true
label: '2000'
tickSize: 5
- value: 2002
grid: true
label: ''
- value: 2004
grid: true
label: ''
- value: 2006
grid: true
label: ''
- value: 2008
grid: true
label: ''
- value: 2010
grid: true
label: '2010'
tickSize: 5
- value: 2012
grid: true
label: ''
- value: 2014
grid: true
label: ''
- value: 2016
grid: true
label: ''
- value: 2018
grid: true
label: ''
- value: 2020
grid: true
label: '2020'
tickSize: 5
min: 2000
max: 2022.5
'y':
min: 0
max: 45
title:
label: Unemployment
grid:
stroke-width: 0.5
ticks:
- value: 0
grid: true
label: 0%
- value: 5
grid: true
label: ''
- value: 10
grid: true
label: 10%
- value: 15
grid: true
label: ''
- value: 20
grid: true
label: 20%
- value: 25
grid: true
label: ''
- value: 30
grid: true
label: 30%
- value: 35
grid: true
label: ''
- value: 40
grid: true
label: 40%
- value: 45
grid: true
label: ''
tick:
size: 5
series:
- title: 16-17
x: decimal_year
y: 16-17→rate (%)1
colour: '#e52e36'
tooltip: 'Age: 16-17<br />{{ Date }}: {{ 16-17→rate (%)1 | toFixed(1) }}%'
- title: 18-24
x: decimal_year
y: 18-24→rate (%)1
colour: '#f7ab3d'
tooltip: 'Age: 18-24<br />{{ Date }}: {{ 18-24→rate (%)1 | toFixed(1) }}%'
- title: 25-49
x: decimal_year
y: 25-49→rate (%)1
colour: '#c7b200'
tooltip: 'Age: 25-49<br />{{ Date }}: {{ 25-49→rate (%)1 | toFixed(1) }}%'
- title: 50-64
x: decimal_year
y: 50 and over→rate (%)1
colour: '#005776'
tooltip: >-
Age: 50 and over<br />{{ Date }}: {{ 50 and over→rate (%)1 | toFixed(1)
}}%
{
"data": "test.data.unemploymentByAge",
"columns": [{
"name": "decimal_year",
"template": "{{ Date | strptime(\"-%b %Y\") | decimalYear() }}"
}],
"legend": {
"show": true
},
"axis": {
"x": {
"title": {
"label": "Year"
},
"grid": {
"stroke-dasharray": "6 2",
"stroke-width": 1
},
"ticks": [{
"value": 2000,
"grid": true,
"label": "2000",
"tickSize": 5
},{
"value": 2002,
"grid": true,
"label": ""
},{
"value": 2004,
"grid": true,
"label": ""
},{
"value": 2006,
"grid": true,
"label": ""
},{
"value": 2008,
"grid": true,
"label": ""
},{
"value": 2010,
"grid": true,
"label": "2010",
"tickSize": 5
},{
"value": 2012,
"grid": true,
"label": ""
},{
"value": 2014,
"grid": true,
"label": ""
},{
"value": 2016,
"grid": true,
"label": ""
},{
"value": 2018,
"grid": true,
"label": ""
},{
"value": 2020,
"grid": true,
"label": "2020",
"tickSize": 5
}],
"min": 2000,
"max": 2022.5
},
"y": {
"min": 0,
"max": 45,
"title": {
"label": "Unemployment"
},
"grid": {
"stroke-width": 0.5
},
"ticks": [{
"value": 0,
"grid": true,
"label": "0%"
},{
"value": 5,
"grid": true,
"label": ""
},{
"value": 10,
"grid": true,
"label": "10%"
},{
"value": 15,
"grid": true,
"label": ""
},{
"value": 20,
"grid": true,
"label": "20%"
},{
"value": 25,
"grid": true,
"label": ""
},{
"value": 30,
"grid": true,
"label": "30%"
},{
"value": 35,
"grid": true,
"label": ""
},{
"value": 40,
"grid": true,
"label": "40%"
},{
"value": 45,
"grid": true,
"label": ""
}],
"tick": {
"size": 5
}
}
},
"series": [{
"title": "16-17",
"x": "decimal_year",
"y": "16-17→rate (%)1",
"colour": "#e52e36",
"tooltip": "Age: 16-17<br />{{ Date }}: {{ 16-17→rate (%)1 | toFixed(1) }}%"
},{
"title": "18-24",
"x": "decimal_year",
"y": "18-24→rate (%)1",
"colour": "#f7ab3d",
"tooltip": "Age: 18-24<br />{{ Date }}: {{ 18-24→rate (%)1 | toFixed(1) }}%"
},{
"title": "25-49",
"x": "decimal_year",
"y": "25-49→rate (%)1",
"colour": "#c7b200",
"tooltip": "Age: 25-49<br />{{ Date }}: {{ 25-49→rate (%)1 | toFixed(1) }}%"
},{
"title": "50-64",
"x": "decimal_year",
"y": "50 and over→rate (%)1",
"colour": "#005776",
"tooltip": "Age: 50 and over<br />{{ Date }}: {{ 50 and over→rate (%)1 | toFixed(1) }}%"
}]
}
4. Category-based data§
This example uses category-based data. Default colours are used as no colour
is given for each series.
This example was made with config
:
legend:
show: true
data:
- category: A
series1: 10
series2: 12
series3: 15
- category: B
series1: 20
series2: 22
series3: 32
- category: C
series1: 23
series2: 21
series3: 24
- category: D
series1: 47
series2: 45
series3: 35
- category: E
series1: 34
series2: 37
series3: 31
- category: F
series1: 55
series2: 57
series3: 52
- category: G
series1: 49
series2: 59
series3: 19
- category: H
series1: 20
series2: 30
series3: 10
- category: I
series1: 10
series2: 12
series3: 1
- category: J
series1: 5
series2: 2
series3: 30
axis:
x:
grid:
show: true
min: -0.5
max: 9.5
ticks:
- value: 0
label: A
- value: 1
label: B
- value: 2
label: C
- value: 3
label: D
- value: 4
label: E
- value: 5
label: F
- value: 6
label: G
- value: 7
label: H
- value: 8
label: I
- value: 9
label: J
'y':
grid:
show: true
tick:
spacing: 25
max: 100
series:
- title: Series 1
x: category
y: series1
- title: Series 2
x: category
y: series2
- title: Series 3
x: category
y: series3
{
"legend": {
"show": true
},
"data": [{
"category": "A",
"series1": 10,
"series2": 12,
"series3": 15
},{
"category": "B",
"series1": 20,
"series2": 22,
"series3": 32
},{
"category": "C",
"series1": 23,
"series2": 21,
"series3": 24
},{
"category": "D",
"series1": 47,
"series2": 45,
"series3": 35
},{
"category": "E",
"series1": 34,
"series2": 37,
"series3": 31
},{
"category": "F",
"series1": 55,
"series2": 57,
"series3": 52
},{
"category": "G",
"series1": 49,
"series2": 59,
"series3": 19
},{
"category": "H",
"series1": 20,
"series2": 30,
"series3": 10
},{
"category": "I",
"series1": 10,
"series2": 12,
"series3": 1
},{
"category": "J",
"series1": 5,
"series2": 2,
"series3": 30
}],
"axis": {
"x": {
"grid": {
"show": true
},
"min": -0.5,
"max": 9.5,
"ticks": [{
"value": 0,
"label": "A"
},{
"value": 1,
"label": "B"
},{
"value": 2,
"label": "C"
},{
"value": 3,
"label": "D"
},{
"value": 4,
"label": "E"
},{
"value": 5,
"label": "F"
},{
"value": 6,
"label": "G"
},{
"value": 7,
"label": "H"
},{
"value": 8,
"label": "I"
},{
"value": 9,
"label": "J"
}]
},
"y": {
"grid": {
"show": true
},
"tick": {
"spacing": 25
},
"max": 100
}
},
"series": [{
"title": "Series 1",
"x": "category",
"y": "series1"
},{
"title": "Series 2",
"x": "category",
"y": "series2"
},{
"title": "Series 3",
"x": "category",
"y": "series3"
}]
}
5. Custom icons§
Line markers can be defined using the points
object on a series
. Points can have a marker
(one of circle
, triangle
, square
, diamond
, pentagon
, hexagon
, octagon
, line
, or cross
), a size
, and a rotation given by rotate
(in degrees). We can also customise the line using stroke-width
, stroke-dasharray
and stroke-linecap
.
This example was made with config
:
legend:
show: true
data:
- value: 0.1
series1: 10
series2: 12
series3: 15
- value: 0.2
series1: 20
series2: 22
series3: 32
- value: 0.3
series1: 23
series2: 21
series3: 24
- value: 0.4
series1: 47
series2: 45
series3: 35
- value: 0.5
series1: 34
series2: 37
series3: 31
- value: 0.6
series1: 55
series2: 57
series3: 52
- value: 0.7
series1: 49
series2: 59
series3: 19
- value: 0.8
series1: 20
series2: 30
series3: 10
- value: 0.9
series1: 10
series2: 12
series3: 1
- value: 1
series1: 5
series2: 2
series3: 30
axis:
x:
grid:
show: true
tick:
spacing: 0.2
'y':
grid:
show: true
tick:
spacing: 25
max: 100
series:
- title: Series 1
x: value
y: series1
points:
size: 8
- title: Series 2
x: value
y: series2
points:
marker: cross
rotate: 45
size: 16
line:
stroke-dasharray: 0 12
- title: Series 3
x: value
y: series3
points:
marker: triangle
rotate: 180
size: 32
line:
stroke-dasharray: 4 6
stroke-width: 3
{
"legend": {
"show": true
},
"data": [{
"value": 0.1,
"series1": 10,
"series2": 12,
"series3": 15
},{
"value": 0.2,
"series1": 20,
"series2": 22,
"series3": 32
},{
"value": 0.3,
"series1": 23,
"series2": 21,
"series3": 24
},{
"value": 0.4,
"series1": 47,
"series2": 45,
"series3": 35
},{
"value": 0.5,
"series1": 34,
"series2": 37,
"series3": 31
},{
"value": 0.6,
"series1": 55,
"series2": 57,
"series3": 52
},{
"value": 0.7,
"series1": 49,
"series2": 59,
"series3": 19
},{
"value": 0.8,
"series1": 20,
"series2": 30,
"series3": 10
},{
"value": 0.9,
"series1": 10,
"series2": 12,
"series3": 1
},{
"value": 1,
"series1": 5,
"series2": 2,
"series3": 30
}],
"axis": {
"x": {
"grid": {
"show": true
},
"tick": {
"spacing": 0.2
}
},
"y": {
"grid": {
"show": true
},
"tick": {
"spacing": 25
},
"max": 100
}
},
"series": [{
"title": "Series 1",
"x": "value",
"y": "series1",
"points": {
"size": 8
}
},{
"title": "Series 2",
"x": "value",
"y": "series2",
"points": {
"marker": "cross",
"rotate": 45,
"size": 16
},
"line": {
"stroke-dasharray": "0 12"
}
},{
"title": "Series 3",
"x": "value",
"y": "series3",
"points": {
"marker": "triangle",
"rotate": 180,
"size": 32
},
"line": {
"stroke-dasharray": "4 6",
"stroke-width": 3
}
}]
}
6. Gaps in series Since v0.15.1§
This is a test to show what happens if data is missing in a series. In this case series 1 is missing a point at x=0.5
and series 2 is missing values for x=0.7
and x=0.8
.
This example was made with config
:
legend:
show: true
data: test.data.scatter-chart-data
axis:
x:
grid:
show: true
tick:
spacing: 0.2
'y':
grid:
show: true
tick:
spacing: 25
max: 100
series:
- title: Series 1
x: value
y: Series 1
points:
size: 8
- title: Series 2
x: value
y: Series 2
points:
marker: cross
rotate: 45
size: 16
line:
stroke-dasharray: 0 12
curvature: 1
- title: Series 3
x: value
y: Series 3
points:
marker: triangle
rotate: 180
size: 32
line:
stroke-dasharray: 4 6
stroke-width: 3
{
"legend": {
"show": true
},
"data": "test.data.scatter-chart-data",
"axis": {
"x": {
"grid": {
"show": true
},
"tick": {
"spacing": 0.2
}
},
"y": {
"grid": {
"show": true
},
"tick": {
"spacing": 25
},
"max": 100
}
},
"series": [{
"title": "Series 1",
"x": "value",
"y": "Series 1",
"points": {
"size": 8
}
},{
"title": "Series 2",
"x": "value",
"y": "Series 2",
"points": {
"marker": "cross",
"rotate": 45,
"size": 16
},
"line": {
"stroke-dasharray": "0 12",
"curvature": 1
}
},{
"title": "Series 3",
"x": "value",
"y": "Series 3",
"points": {
"marker": "triangle",
"rotate": 180,
"size": 32
},
"line": {
"stroke-dasharray": "4 6",
"stroke-width": 3
}
}]
}
7. Limiting a series to specific rows Since 0.16.5§
Sometimes you may have a big, stacked, file where you may want to use some rows for one series and other rows for another. We can limit a particular series
to only use certain rows by using the option where
. In the example below we have a dataset relating to housing that has a column geography_name_x
that contains English local authorities. We can create a series for just Leeds
and another for just the City of London
.
This example was made with config
:
legend:
show: true
data: test.data.house-prices
axis:
x:
grid:
show: true
tick:
spacing: 5
'y':
grid:
show: true
tick:
spacing: 25
title:
label: Vacants per 1000 dwellings
series:
- title: Leeds
x: date
y: vacants_per_thousand_dwellings
where: '"geography_name_x"="Leeds"'
- title: City of London
x: date
y: vacants_per_thousand_dwellings
where: '"geography_name_x"="City of London"'
{
"legend": {
"show": true
},
"data": "test.data.house-prices",
"axis": {
"x": {
"grid": {
"show": true
},
"tick": {
"spacing": 5
}
},
"y": {
"grid": {
"show": true
},
"tick": {
"spacing": 25
},
"title": {
"label": "Vacants per 1000 dwellings"
}
}
},
"series": [{
"title": "Leeds",
"x": "date",
"y": "vacants_per_thousand_dwellings",
"where": "\"geography_name_x\"=\"Leeds\""
},{
"title": "City of London",
"x": "date",
"y": "vacants_per_thousand_dwellings",
"where": "\"geography_name_x\"=\"City of London\""
}]
}