Skip to main content

OWID charts for rendering in Jupyter notebooks.

Project description

owid-grapher-py

Create interactive Our World in Data charts in Jupyter notebooks.

Status

✅ Working (experimental)

This package uses the OWID Grapher library to render interactive charts. The API may change as OWID's internal APIs evolve.

Requirements

  • Python 3.10+
  • Jupyter notebook or JupyterLab

Installing

pip install owid-grapher-py

Quick Start

See the quickstart notebook for a comprehensive walkthrough with examples.

Get your data into a tidy data frame, then wrap it in a chart object and explain what marks you want and how to encode the dimensions you have (inspired by Altair).

import pandas as pd
from owid.grapher import Chart

# Create sample data
df = pd.DataFrame({
    'year': [2000, 2005, 2010, 2015, 2020] * 3,
    'country': ['Australia'] * 5 + ['New Zealand'] * 5 + ['Japan'] * 5,
    'population': [19.2, 20.4, 22.0, 23.8, 25.7,
                   3.9, 4.1, 4.4, 4.6, 5.1,
                   126.8, 127.8, 128.1, 127.1, 125.8]
})

# Create an interactive line chart
Chart(df).mark_line().encode(
    x='year',
    y='population',
    entity='country'
).label(title='Population Over Time')

Chart Types

Line Chart

Chart(df).mark_line().encode(
    x='year',
    y='population',
    entity='country'  # group by country
).label(title='Population by Country')

Bar Chart

# Simple bar chart
Chart(df_2020).mark_bar().encode(
    x='population',
    y='country'
).label(title='Population in 2020')

# Stacked bar chart
Chart(df).mark_bar(stacked=True).encode(
    x='energy_generated',
    y='country',
    entity='energy_source'
)

Scatter Plot

# Basic scatter plot
Chart(df).mark_scatter().encode(
    x='gdp_per_capita',
    y='life_expectancy'
).label(title='GDP vs Life Expectancy')

# Scatter plot with entity grouping
Chart(df).mark_scatter().encode(
    x='gdp_per_capita',
    y='life_expectancy',
    entity='country'  # group by country
).label(title='GDP vs Life Expectancy by Country')

# Scatter plot with color and size encoding
Chart(df).mark_scatter().encode(
    x='gdp_per_capita',
    y='life_expectancy',
    entity='country',
    color='continent',  # color by a different variable
    size='population'   # size bubbles by population
).label(title='GDP vs Life Expectancy')

Map View

# Enable map tab (opens to map by default)
Chart(df).mark_line().encode(
    x='year',
    y='population',
    entity='country'
).interact(enable_map=True)

Labels

Chart(df).mark_line().encode(
    x='year',
    y='population',
    entity='country'
).label(
    title='Population Trends',
    subtitle='Select countries to compare',
    note='Data is illustrative',
    source_desc='Sample data'
)

Axis Configuration

# Configure individual axes
Chart(df).mark_scatter().encode(
    x='gdp_per_capita',
    y='life_expectancy',
    entity='country'
).xaxis(
    label='GDP per Capita',
    unit='$',
    scale='log',              # Use logarithmic scale
    scale_control=True        # Allow user to toggle log/linear
).yaxis(
    label='Life Expectancy',
    unit='years'
)

# Or configure both axes at once
Chart(df).mark_scatter().encode(
    x='gdp_per_capita',
    y='life_expectancy',
    entity='country'
).axis(
    x_label='GDP per Capita',
    y_label='Life Expectancy',
    x_unit='$',
    y_unit='years',
    x_scale='log',
    x_scale_control=True
)

Interactivity

# Enable relative mode toggle
Chart(...).interact(allow_relative=True)

# Enable log/linear scale toggle
Chart(...).interact(scale_control=True)

# Enable country/entity picker
Chart(...).interact(entity_control=True)

# Enable map tab
Chart(...).interact(enable_map=True)

# Combine multiple options
Chart(df).mark_line().encode(
    x='year', y='population', entity='country'
).interact(
    allow_relative=True,
    entity_control=True,
    enable_map=True
)

Data Selection

# Select specific entities and time range
Chart(df).mark_line().encode(
    x='year', y='population', entity='country'
).select(
    entities=['Australia', 'Japan'],
    timespan=(2000, 2015)
)

Transforms

# Plot relative change
Chart(...).transform(relative=True)

Filtering

# Only show entities that have data for all dimensions
# Useful for scatter plots where you need both x and y values
Chart(df).mark_scatter().encode(
    x='gdp_per_capita',
    y='life_expectancy',
    entity='country'
).filter(matching_entities_only=True)

Export Config

View the underlying JSON configuration:

chart = Chart(df).mark_line().encode(x='year', y='population', entity='country')
chart.export()  # Returns the grapher config dict

How It Works

OWID's Grapher library uses a JSON config format for all charts. This package:

  1. Takes your pandas DataFrame and chart configuration
  2. Converts it to the Grapher's internal format (CSV + GrapherState config)
  3. Renders an iframe in Jupyter that loads the OWID Grapher library
  4. The Grapher library renders the interactive chart

Development

# Clone the repo
git clone https://github.com/owid/owid-grapher-py
cd owid-grapher-py

# Install dependencies
make .venv

# Run tests
make test

# Check changed files
make check

For Developers

Useful resources when working with OWID charts:

  • Chart configs: Available for any existing chart by appending .config.json to the URL

    • Example: https://ourworldindata.org/grapher/annual-co2-emissions-per-country.config.json
  • Grapher schema: The complete schema for chart configurations

    • Latest: https://files.ourworldindata.org/schemas/grapher-schema.009.json
  • ColumnDef schema: TypeScript definition for column metadata

Testing with real charts:

To replicate an existing OWID chart in a notebook:

  1. Fetch the chart config from the .config.json endpoint
  2. Download the data using .csv?useColumnShortNames=true
  3. Map the config properties to the Chart API methods

TODO

This project should not attempt feature parity with grapher, but should walk the line between making an expressive charting tool and making something that can reproduce a large percentage of our existing charts. Some ideas for improvement:

Enable grapher.Chart() to support more chart types:

  • Scatterplots with color and size encoding
  • Axis labels and units
  • Log/linear scale controls
  • Entity filtering (matching_entities_only)
  • Axis bounds (min/max values)
  • Line charts without a time axis

Auto-generate more types of notebooks correctly

  • Multi-variable single entity line-charts
  • Bar charts
  • Stacked bar charts
  • Time selection

Changelog

  • 0.2.2
    • Fix quickstart notebook to handle autoreload gracefully in Google Colab
  • 0.2.1
    • Add comprehensive PyPI metadata (keywords, classifiers, project URLs)
    • Add README.md as package long description
    • Update installation instructions to use PyPI
  • 0.2.0
    • Add scatter plot support with color and size encoding
    • Add xaxis() and yaxis() methods for axis configuration
    • Add support for logarithmic scales with scale='log'
    • Add scale_control parameter for user-toggleable log/linear scales
    • Add axis labels and units support
    • Add filter(matching_entities_only=True) for filtering entities with complete data
    • Add comprehensive quickstart notebook with real-world examples
    • Update documentation with all new features
  • 0.1.6
    • Update to new GrapherState API with OwidTable
    • Fix iframe scroll behavior in notebooks
    • Hide unnecessary UI elements for cleaner notebook display
    • Update dependencies to match owid-catalog requirements
  • 0.1.5
    • Update to new module layout and Grapher config changes
  • 0.1.4
    • Fix broken charts by updating embedded JS requests
  • 0.1.3
    • Do not render the data when auto-generating notebooks
    • Allow fetching data by slug
    • Allow fetching data and config from dev environments
  • 0.1.2
    • Support timespans with select()
  • 0.1.1
    • Improve select(), interact() and label() methods on Chart
    • Helpers to download config/data from chart pages (owid.site)
    • Generate notebooks with Python plotting commands (owid.grapher.notebook)
  • 0.1.0
    • Plot basic line charts, bar charts and stacked bar charts

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

owid_grapher_py-0.2.2.tar.gz (2.0 MB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

owid_grapher_py-0.2.2-py3-none-any.whl (14.7 kB view details)

Uploaded Python 3

File details

Details for the file owid_grapher_py-0.2.2.tar.gz.

File metadata

  • Download URL: owid_grapher_py-0.2.2.tar.gz
  • Upload date:
  • Size: 2.0 MB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.12

File hashes

Hashes for owid_grapher_py-0.2.2.tar.gz
Algorithm Hash digest
SHA256 8731fd9a06e2f5a273536e095558e2db3c1a9ed0376df7e4846a3595ad3dfd63
MD5 8e7792dd238e77f1fb59020d75f29fd0
BLAKE2b-256 3e1e4f4fb8a8e96f8330eea67dc7ad4889f1952a366f260dcddea92876b3915a

See more details on using hashes here.

File details

Details for the file owid_grapher_py-0.2.2-py3-none-any.whl.

File metadata

File hashes

Hashes for owid_grapher_py-0.2.2-py3-none-any.whl
Algorithm Hash digest
SHA256 f463909c870dfe6ac8d9a8d99b15f82fffb964109e275d8e549ed1525ad17859
MD5 819dfd8fddd0efd407ada5bc086a69d4
BLAKE2b-256 eab812f158f0f53cae3651bf9a6eacc641ab7ba274607842785997ba56c1425c

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page