Examples#

Data series#

Simple pairs#

import leather

data = [
    (0, 3),
    (4, 5),
    (7, 9),
    (8, 4)
]

chart = leather.Chart('Simple pairs')
chart.add_dots(data)
chart.to_svg('examples/charts/simple_pairs.svg')
_images/simple_pairs.svg

Table from csv.reader#

Sequence row data, such as is returned by csv.reader() can be accessed by specifying the indices of the columns containing the x and y values.

Note that leather does not automatically convert numerical strings, such as those stored in a CSV. If you want that you’ll need to use a smarter table reader, such as agate

import csv

import leather

with open('examples/realdata/gii.csv') as f:
    reader = csv.reader(f)
    next(reader)
    data = list(reader)[:10]

    for row in data:
        row[1] = float(row[1]) if row[1] is not None else None

chart = leather.Chart('Data from CSV reader')
chart.add_bars(data, x=1, y=0)
chart.to_svg('examples/charts/csv_reader.svg')
_images/csv_reader.svg

Table from csv.DictReader#

Dict row data, such as is returned by csv.DictReader can be accessed by specifying the indices of the columns containing the x and y values.

See previous example for note on strings from CSVs.

import csv

import leather

with open('examples/realdata/gii.csv') as f:
    reader = csv.DictReader(f)
    data = list(reader)[:10]

    for row in data:
        mmr = row['Maternal mortality ratio']
        row['Maternal mortality ratio'] = float(mmr) if mmr is not None else None

chart = leather.Chart('Data from CSV reader')
chart.add_bars(data, x='Maternal mortality ratio', y='Country')
chart.to_svg('examples/charts/csv_dict_reader.svg')
_images/csv_dict_reader.svg

Custom data#

Completely custom data formats are also supported via accessor functions.

import leather

data = [
    {'x': 0, 'q': {'y': [3]}},
    {'x': 4, 'q': {'y': [5]}},
    {'x': 7, 'q': {'y': [9]}},
    {'x': 8, 'q': {'y': [4]}},
]


def x(row, index):
    return row['x']


def y(row, index):
    return row['q']['y'][0]


chart = leather.Chart('Line')
chart.add_line(data, x=x, y=y)
chart.to_svg('examples/charts/custom_data.svg')
_images/custom_data.svg

Multiple series#

Multiple data series can be displayed on a single chart so long as they all use the same type of Scale.

import leather

data1 = [
    (0, 3),
    (4, 5),
    (7, 9),
    (8, 4)
]

data2 = [
    (2, 4),
    (7, 3),
    (6, 2),
    (5, 9)
]

chart = leather.Chart('Multiple series')
chart.add_dots(data1)
chart.add_dots(data2)
chart.to_svg('examples/charts/multiple_series.svg')
_images/multiple_series.svg

Shapes#

Bars#

import leather

data = [
    (3, 'Hello'),
    (5, 'How'),
    (9, 'Are'),
    (4, 'You')
]

chart = leather.Chart('Bars')
chart.add_bars(data)
chart.to_svg('examples/charts/bars.svg')
_images/bars.svg

Columns#

import leather

data = [
    ('Hello', 3),
    ('How', 5),
    ('Are', 9),
    ('You', 4)
]

chart = leather.Chart('Columns')
chart.add_columns(data)
chart.to_svg('examples/charts/columns.svg')
_images/columns.svg

Dots#

import leather

data = [
    (0, 3),
    (4, 5),
    (7, 9),
    (8, 4)
]

chart = leather.Chart('Dots')
chart.add_dots(data)
chart.to_svg('examples/charts/dots.svg')
_images/dots.svg

Lines#

import leather

data = [
    (0, 3),
    (4, 5),
    (7, 9),
    (8, 4)
]

chart = leather.Chart('Line')
chart.add_line(data)
chart.to_svg('examples/charts/lines.svg')
_images/lines.svg

Mixing shapes#

You can mix different shapes for different series on the same chart.

import leather

line_data = [
    (0, 1),
    (2, 5),
    (4, 4),
    (8, 3)
]

dot_data = [
    (1, 3),
    (2, 5),
    (6, 9),
    (10, 4)
]

chart = leather.Chart('Mixed shapes')
chart.add_line(line_data)
chart.add_dots(dot_data)
chart.to_svg('examples/charts/mixed_shapes.svg')
_images/mixed_shapes.svg

Scales#

Linear#

When using numerical data Linear scales are created automatically and by default. You may override the domain by adding a scale manually.

import leather

data = [
    (0, 3),
    (4, 5),
    (7, 9),
    (8, 4)
]

chart = leather.Chart('Linear')
chart.add_x_scale(0, 20)
chart.add_y_scale(-10, 10)
chart.add_line(data)
chart.to_svg('examples/charts/linear.svg')
_images/linear.svg

Ordinal#

When using text data Ordinal scales are created automatically and by default. It is generally not useful to override these defaults.

import leather

data = [
    ('Hello', 3),
    ('How', 5,),
    ('Are', 9),
    ('You', 4)
]

chart = leather.Chart('Ordinal')
chart.add_columns(data)
chart.to_svg('examples/charts/ordinal.svg')
_images/ordinal.svg

Temporal#

When using date/time data Temporal scales are created automatically and by default. You may override the domain by adding a scale manually.

from datetime import date

import leather

data = [
    (date(2015, 1, 1), 3),
    (date(2015, 3, 1), 5),
    (date(2015, 6, 1), 9),
    (date(2015, 9, 1), 4)
]

chart = leather.Chart('Temporal')
chart.add_x_scale(date(2014, 1, 1), date(2016, 1, 1))
chart.add_line(data)
chart.to_svg('examples/charts/temporal.svg')
_images/temporal.svg

Axes#

Changing tick values#

You can change the list of ticks that are displayed using Chart.add_x_axis() and Chart.add_y_axis() methods. This will not adjust automatically adjust the scale, so it is possible to pick tick values that are not displayed.

import leather

data = [
    (0, 3),
    (4, 5),
    (7, 9),
    (8, 4)
]

chart = leather.Chart('Line')
chart.add_x_scale(0, 10)
chart.add_x_axis(ticks=[0, 10])
chart.add_line(data)
chart.to_svg('examples/charts/ticks.svg')
_images/ticks.svg

Customizing tick format#

You can provide a tick formatter method to change how ticks are displayed using the Chart.add_x_axis() and Chart.add_y_axis() methods.

import leather

data = [
    (0, 3),
    (4, 5),
    (7, 9),
    (8, 4)
]


def tick_formatter(value, index, tick_count):
    return '%i (%i/%i)' % (value, index, tick_count)


chart = leather.Chart('Line')
chart.add_x_axis(tick_formatter=tick_formatter)
chart.add_line(data)
chart.to_svg('examples/charts/tick_format.svg')
_images/tick_format.svg

Styling#

Changing theme values#

Chart styles are set using a dead simple theme system. Leather is meant for making quick and dirty charts. It is neither expected nor recommended for user’s to customize these styles.

import leather

line_data = [
    (0, 1),
    (2, 5),
    (4, 4),
    (8, 3)
]

dot_data = [
    (1, 3),
    (2, 5),
    (6, 9),
    (10, 4)
]

leather.theme.title_font_family = 'Comic Sans MS'
leather.theme.legend_font_family = 'Comic Sans MS'
leather.theme.tick_font_family = 'Comic Sans MS'
leather.theme.default_series_colors = ['#ff0000', '#00ff00']

chart = leather.Chart('Theme')
chart.add_line(line_data)
chart.add_dots(dot_data)
chart.to_svg('examples/charts/theme.svg')
_images/theme.svg

Changing series colors#

More practically, individual default Series colors can be overridden when they are created.

import leather

data = [
    ('Hello', 3),
    ('How', 5),
    ('Are', 9),
    ('You', 4)
]

chart = leather.Chart('Series color')
chart.add_columns(data, fill_color='#000000')
chart.to_svg('examples/charts/series_color.svg')
_images/series_color.svg

Styling data based on value#

Style attributes of individual data points can be set by value using a style_function().

import random

import leather

dot_data = [(random.randint(0, 250), random.randint(0, 250)) for i in range(100)]


def colorizer(d):
    return 'rgb(%i, %i, %i)' % (d.x, d.y, 150)


chart = leather.Chart('Colorized dots')
chart.add_dots(dot_data, fill_color=colorizer)
chart.to_svg('examples/charts/colorized_dots.svg')
_images/colorized_dots.svg

Creating dashed lines#

When using Chart.add_line(), you can set the stroke_dasharray property.

import leather

data = [
    (0, 3),
    (4, 5),
    (7, 9),
    (8, 4)
]

chart = leather.Chart('Line Dashes')
chart.add_line(data, stroke_dasharray='2%')
chart.to_svg('examples/charts/lines_dashes.svg')
_images/lines_dashes.svg

Chart grids#

With mixed scales#

You can add charts of completely different types to a single graphic by using Grid.

import leather

data1 = [
    (0, 3),
    (4, 5),
    (7, 9),
    (8, 4)
]

data2 = [
    (3, 4),
    (5, 6),
    (7, 10),
    (8, 2)
]

chart1 = leather.Chart('Dots')
chart1.add_dots(data1)

chart2 = leather.Chart('Lines')
chart2.add_line(data2)

grid = leather.Grid()
grid.add_one(chart1)
grid.add_one(chart2)
grid.to_svg('examples/charts/grid.svg')
_images/grid.svg

With consistent scales#

A grid of charts can automatically be synchronized to a consistent view using Lattice.

import leather

data1 = [
    (0, 3),
    (4, 5),
    (7, 9),
    (8, 4)
]

data2 = [
    (3, 4),
    (3, 4),
    (5, 6),
    (7, 10),
    (8, 2)
]

data3 = [
    (2, 4),
    (3, 5),
    (6, 2),
    (8, 3),
    (10, 5)
]

lattice = leather.Lattice()
lattice.add_many([data1, data2, data3], titles=['First', 'Second', 'Third'])
lattice.to_svg('examples/charts/lattice.svg')
_images/lattice.svg