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')

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')

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')

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')

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')

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')

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')

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')

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')

Mixing shapes

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

import leather

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

line_data = [
    ('Hello', 1),
    ('How', 5),
    ('Are', 4),
    ('You', 3)
]

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

chart = leather.Chart('Mixed shapes')
chart.add_columns(column_data)
chart.add_line(line_data)
chart.add_dots(dot_data)
chart.to_svg('examples/charts/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')

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')

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')

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')

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')

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

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

line_data = [
    ('Hello', 1),
    ('How', 5),
    ('Are', 4),
    ('You', 3)
]

dot_data = [
    ('Hello', 3),
    ('How', 5),
    ('Are', 9),
    ('You', 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', '#0000ff']

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

Changing series colors

More practically, individual default Series colors can be overriden 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')

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')

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')

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')