Skip to content

Grapher

owid.grapher.Chart

Chart(data: DataFrame)

Create interactive OWID charts from pandas DataFrames.

The Chart class provides a declarative API for building interactive visualizations using OWID's Grapher library. Charts are configured through method chaining and render directly in Jupyter notebooks.

Multiple chart types can be enabled by chaining mark_*() methods. The first one called becomes the default view, or use show() to set a specific default tab.

PARAMETER DESCRIPTION
data

A pandas DataFrame containing the data to visualize. The DataFrame should have columns for time/x-axis, values/y-axis, and optionally entities for grouping.

TYPE: DataFrame

Example
import pandas as pd
from owid.grapher import Chart

df = pd.DataFrame({
    'year': [2020, 2021, 2022],
    'country': ['USA', 'China', 'India'],
    'gdp': [21.4, 14.7, 2.9]
})

# Single chart type
Chart(df).mark_line().encode(
    x='year',
    y='gdp',
    entity='country'
).label(
    title='GDP by Country'
)

# Multiple chart types with bar as default
Chart(df).mark_line().mark_bar().show("discrete-bar").encode(...)
Source code in owid/grapher/__init__.py
def __init__(self, data: pd.DataFrame):
    self.data = data.copy()
    self.config = ChartConfig()
    self.chart_types: List[str] = []  # Available chart types
    self.default_tab: Optional[str] = None  # Which tab to show by default
    self.x: Optional[str] = None
    self.y: Optional[str] = None
    self.entity: Optional[str] = None
    self.color: Optional[str] = None
    self.size: Optional[str] = None
    self.time_type = TimeType.YEAR
    self.selection: Optional[List[str]] = None
    self.timespan: Optional[Tuple[Any, Any]] = None
    self.x_unit: Optional[str] = None
    self.y_unit: Optional[str] = None
    self.variable_configs: Dict[str, "VariableConfig"] = {}  # Column metadata

encode

encode(
    x: Optional[str] = None,
    y: Optional[str] = None,
    entity: Optional[str] = None,
    color: Optional[str] = None,
    size: Optional[str] = None,
) -> Chart

Map DataFrame columns to visual properties.

This method establishes the visual encoding by mapping DataFrame columns to chart dimensions. The behavior varies by chart type:

  • Line/Bar charts: x is time, y is values, entity groups lines/bars
  • Scatter plots: x and y are both numeric values, entity groups points
PARAMETER DESCRIPTION
x

Column name for x-axis. For line/bar charts, typically a time column ('year', 'date'). For scatter plots, a numeric value column.

TYPE: Optional[str] DEFAULT: None

y

Column name for y-axis values to plot. For bar charts, can be the entity column if you want entities on the y-axis.

TYPE: Optional[str] DEFAULT: None

entity

Column name for grouping data (e.g., 'country', 'region'). Each unique value becomes a separate line/series. Optional for single-series charts.

TYPE: Optional[str] DEFAULT: None

color

Column name for color encoding in scatter plots. Values map to colors.

TYPE: Optional[str] DEFAULT: None

size

Column name for size encoding in scatter plots. Values map to point sizes.

TYPE: Optional[str] DEFAULT: None

RETURNS DESCRIPTION
Chart

Self for method chaining.

RAISES DESCRIPTION
ValueError

If a specified column name is not found in the DataFrame.

Example
# Line chart with multiple countries
Chart(df).mark_line().encode(
    x='year',
    y='population',
    entity='country'
)

# Scatter plot with color and size
Chart(df).mark_scatter().encode(
    x='gdp_per_capita',
    y='life_expectancy',
    entity='country',
    color='continent',
    size='population'
)
Source code in owid/grapher/__init__.py
def encode(
    self,
    x: Optional[str] = None,
    y: Optional[str] = None,
    entity: Optional[str] = None,
    color: Optional[str] = None,
    size: Optional[str] = None,
) -> "Chart":
    """Map DataFrame columns to visual properties.

    This method establishes the visual encoding by mapping DataFrame columns to
    chart dimensions. The behavior varies by chart type:

    - **Line/Bar charts**: `x` is time, `y` is values, `entity` groups lines/bars
    - **Scatter plots**: `x` and `y` are both numeric values, `entity` groups points

    Args:
        x: Column name for x-axis. For line/bar charts, typically a time column
            ('year', 'date'). For scatter plots, a numeric value column.
        y: Column name for y-axis values to plot. For bar charts, can be the entity
            column if you want entities on the y-axis.
        entity: Column name for grouping data (e.g., 'country', 'region'). Each unique
            value becomes a separate line/series. Optional for single-series charts.
        color: Column name for color encoding in scatter plots. Values map to colors.
        size: Column name for size encoding in scatter plots. Values map to point sizes.

    Returns:
        Self for method chaining.

    Raises:
        ValueError: If a specified column name is not found in the DataFrame.

    Example:
        ```python
        # Line chart with multiple countries
        Chart(df).mark_line().encode(
            x='year',
            y='population',
            entity='country'
        )

        # Scatter plot with color and size
        Chart(df).mark_scatter().encode(
            x='gdp_per_capita',
            y='life_expectancy',
            entity='country',
            color='continent',
            size='population'
        )
        ```
    """
    self.x = x
    self.y = y
    self.entity = entity
    self.color = color
    self.size = size

    # fail early if there's been a typo
    for col in [x, y, entity, color, size]:
        if col and col not in self.data.columns:
            raise ValueError(f"no such column: {col}")

    if x == "date":
        self.time_type = TimeType.DAY

    self.config.hide_legend = not entity

    return self

label

label(
    title: str = "",
    subtitle: str = "",
    source_desc: str = "",
    note: str = "",
) -> Chart

Add labels and text to the chart.

PARAMETER DESCRIPTION
title

Chart title.

TYPE: str DEFAULT: ''

subtitle

Chart subtitle.

TYPE: str DEFAULT: ''

source_desc

Data source attribution.

TYPE: str DEFAULT: ''

note

Additional notes or footnotes.

TYPE: str DEFAULT: ''

RETURNS DESCRIPTION
Chart

Self for method chaining.

Source code in owid/grapher/__init__.py
def label(
    self, title: str = "", subtitle: str = "", source_desc: str = "", note: str = ""
) -> "Chart":
    """Add labels and text to the chart.

    Args:
        title: Chart title.
        subtitle: Chart subtitle.
        source_desc: Data source attribution.
        note: Additional notes or footnotes.

    Returns:
        Self for method chaining.
    """
    self.config.title = title
    self.config.subtitle = subtitle
    self.config.source_desc = source_desc
    self.config.note = note
    return self

xaxis

xaxis(
    label: Optional[str] = None,
    unit: Optional[str] = None,
    scale: Optional[Literal["linear", "log"]] = None,
    scale_control: Optional[bool] = None,
) -> Chart

Configure the x-axis.

PARAMETER DESCRIPTION
label

Axis label text.

TYPE: Optional[str] DEFAULT: None

unit

Unit of measurement (e.g., '$', 'kg').

TYPE: Optional[str] DEFAULT: None

scale

Scale type ('linear' or 'log').

TYPE: Optional[Literal['linear', 'log']] DEFAULT: None

scale_control

Allow users to toggle scale.

TYPE: Optional[bool] DEFAULT: None

RETURNS DESCRIPTION
Chart

Self for method chaining.

Source code in owid/grapher/__init__.py
def xaxis(
    self,
    label: Optional[str] = None,
    unit: Optional[str] = None,
    scale: Optional[Literal["linear", "log"]] = None,
    scale_control: Optional[bool] = None,
) -> "Chart":
    """Configure the x-axis.

    Args:
        label: Axis label text.
        unit: Unit of measurement (e.g., '$', 'kg').
        scale: Scale type ('linear' or 'log').
        scale_control: Allow users to toggle scale.

    Returns:
        Self for method chaining.
    """
    if label is not None:
        self.config.x_axis["label"] = label
    if unit is not None:
        self.x_unit = unit
    if scale is not None:
        self.config.x_axis["scaleType"] = scale
    if scale_control is not None:
        self.config.x_axis["canChangeScaleType"] = scale_control
    return self

yaxis

yaxis(
    label: Optional[str] = None,
    unit: Optional[str] = None,
    scale: Optional[Literal["linear", "log"]] = None,
    scale_control: Optional[bool] = None,
) -> Chart

Configure the y-axis.

PARAMETER DESCRIPTION
label

Axis label text.

TYPE: Optional[str] DEFAULT: None

unit

Unit of measurement (e.g., '$', 'kg').

TYPE: Optional[str] DEFAULT: None

scale

Scale type ('linear' or 'log').

TYPE: Optional[Literal['linear', 'log']] DEFAULT: None

scale_control

Allow users to toggle scale.

TYPE: Optional[bool] DEFAULT: None

RETURNS DESCRIPTION
Chart

Self for method chaining.

Source code in owid/grapher/__init__.py
def yaxis(
    self,
    label: Optional[str] = None,
    unit: Optional[str] = None,
    scale: Optional[Literal["linear", "log"]] = None,
    scale_control: Optional[bool] = None,
) -> "Chart":
    """Configure the y-axis.

    Args:
        label: Axis label text.
        unit: Unit of measurement (e.g., '$', 'kg').
        scale: Scale type ('linear' or 'log').
        scale_control: Allow users to toggle scale.

    Returns:
        Self for method chaining.
    """
    if label is not None:
        self.config.y_axis["label"] = label
    if unit is not None:
        self.y_unit = unit
    if scale is not None:
        self.config.y_axis["scaleType"] = scale
    if scale_control is not None:
        self.config.y_axis["canChangeScaleType"] = scale_control
    return self

axis

axis(
    x_label: Optional[str] = None,
    y_label: Optional[str] = None,
    x_unit: Optional[str] = None,
    y_unit: Optional[str] = None,
    x_scale: Optional[Literal["linear", "log"]] = None,
    y_scale: Optional[Literal["linear", "log"]] = None,
    x_scale_control: Optional[bool] = None,
    y_scale_control: Optional[bool] = None,
) -> Chart

Configure both axes at once.

Convenience method for setting properties on both axes. For single-axis configuration, use xaxis() or yaxis() instead.

PARAMETER DESCRIPTION
x_label

Label text for x-axis.

TYPE: Optional[str] DEFAULT: None

y_label

Label text for y-axis.

TYPE: Optional[str] DEFAULT: None

x_unit

Unit suffix for x-axis values (e.g., '$', '%', 'kg').

TYPE: Optional[str] DEFAULT: None

y_unit

Unit suffix for y-axis values.

TYPE: Optional[str] DEFAULT: None

x_scale

Scale type for x-axis ('linear' or 'log').

TYPE: Optional[Literal['linear', 'log']] DEFAULT: None

y_scale

Scale type for y-axis ('linear' or 'log').

TYPE: Optional[Literal['linear', 'log']] DEFAULT: None

x_scale_control

If True, adds UI control to toggle x-axis scale.

TYPE: Optional[bool] DEFAULT: None

y_scale_control

If True, adds UI control to toggle y-axis scale.

TYPE: Optional[bool] DEFAULT: None

RETURNS DESCRIPTION
Chart

Self for method chaining.

Source code in owid/grapher/__init__.py
def axis(
    self,
    x_label: Optional[str] = None,
    y_label: Optional[str] = None,
    x_unit: Optional[str] = None,
    y_unit: Optional[str] = None,
    x_scale: Optional[Literal["linear", "log"]] = None,
    y_scale: Optional[Literal["linear", "log"]] = None,
    x_scale_control: Optional[bool] = None,
    y_scale_control: Optional[bool] = None,
) -> "Chart":
    """Configure both axes at once.

    Convenience method for setting properties on both axes. For single-axis
    configuration, use xaxis() or yaxis() instead.

    Args:
        x_label: Label text for x-axis.
        y_label: Label text for y-axis.
        x_unit: Unit suffix for x-axis values (e.g., '$', '%', 'kg').
        y_unit: Unit suffix for y-axis values.
        x_scale: Scale type for x-axis ('linear' or 'log').
        y_scale: Scale type for y-axis ('linear' or 'log').
        x_scale_control: If True, adds UI control to toggle x-axis scale.
        y_scale_control: If True, adds UI control to toggle y-axis scale.

    Returns:
        Self for method chaining.
    """
    if x_label is not None:
        self.config.x_axis["label"] = x_label
    if y_label is not None:
        self.config.y_axis["label"] = y_label
    if x_unit is not None:
        self.x_unit = x_unit
    if y_unit is not None:
        self.y_unit = y_unit
    if x_scale is not None:
        self.config.x_axis["scaleType"] = x_scale
    if y_scale is not None:
        self.config.y_axis["scaleType"] = y_scale
    if x_scale_control is not None:
        self.config.x_axis["canChangeScaleType"] = x_scale_control
    if y_scale_control is not None:
        self.config.y_axis["canChangeScaleType"] = y_scale_control
    return self

mark_scatter

mark_scatter() -> Chart

Add scatter plot to available chart types.

Scatter plots display individual data points with x and y positions. Use color and size encodings for additional dimensions. Best for showing relationships between two numeric variables.

Can be combined with other mark_*() methods to enable multiple chart types.

RETURNS DESCRIPTION
Chart

Self for method chaining.

Source code in owid/grapher/__init__.py
def mark_scatter(self) -> "Chart":
    """Add scatter plot to available chart types.

    Scatter plots display individual data points with x and y positions. Use `color`
    and `size` encodings for additional dimensions. Best for showing relationships
    between two numeric variables.

    Can be combined with other mark_*() methods to enable multiple chart types.

    Returns:
        Self for method chaining.
    """
    self._add_chart_type("ScatterPlot")
    return self

mark_line

mark_line() -> Chart

Add line chart to available chart types.

Line charts connect data points with lines, ideal for showing trends over time. Multiple entities create multiple lines.

Can be combined with other mark_*() methods to enable multiple chart types.

RETURNS DESCRIPTION
Chart

Self for method chaining.

Source code in owid/grapher/__init__.py
def mark_line(self) -> "Chart":
    """Add line chart to available chart types.

    Line charts connect data points with lines, ideal for showing trends over time.
    Multiple entities create multiple lines.

    Can be combined with other mark_*() methods to enable multiple chart types.

    Returns:
        Self for method chaining.
    """
    self._add_chart_type("LineChart")
    return self

mark_bar

mark_bar(stacked: bool = False) -> Chart

Add bar chart to available chart types.

Bar charts display categorical data with rectangular bars. Bars can be shown side-by-side (default) or stacked on top of each other.

Can be combined with other mark_*() methods to enable multiple chart types.

PARAMETER DESCRIPTION
stacked

If True, creates a stacked bar chart where bars for different entities are stacked vertically. If False (default), bars are shown side-by-side.

TYPE: bool DEFAULT: False

RETURNS DESCRIPTION
Chart

Self for method chaining.

Source code in owid/grapher/__init__.py
def mark_bar(self, stacked: bool = False) -> "Chart":
    """Add bar chart to available chart types.

    Bar charts display categorical data with rectangular bars. Bars can be shown
    side-by-side (default) or stacked on top of each other.

    Can be combined with other mark_*() methods to enable multiple chart types.

    Args:
        stacked: If True, creates a stacked bar chart where bars for different
            entities are stacked vertically. If False (default), bars are shown
            side-by-side.

    Returns:
        Self for method chaining.
    """
    chart_type = "StackedDiscreteBar" if stacked else "DiscreteBar"
    self._add_chart_type(chart_type)
    return self

mark_map

mark_map(
    time_tolerance: Optional[int] = None,
    color_scheme: Optional[ColorSchemeName] = None,
    binning_strategy: Optional[BinningStrategy] = None,
    custom_numeric_values: Optional[List[float]] = None,
) -> Chart

Enable the map tab with optional configuration.

Adds a world map visualization showing data geographically. Can be combined with other mark_*() methods.

PARAMETER DESCRIPTION
time_tolerance

How many years to look back/forward for data

TYPE: Optional[int] DEFAULT: None

color_scheme

Color scheme name (e.g., "Reds", "Blues", "YlOrRd")

TYPE: Optional[ColorSchemeName] DEFAULT: None

binning_strategy

How to bin values ("auto", "manual", "equalInterval", "quantiles")

TYPE: Optional[BinningStrategy] DEFAULT: None

custom_numeric_values

Custom bin boundaries when using manual binning

TYPE: Optional[List[float]] DEFAULT: None

RETURNS DESCRIPTION
Chart

Self for method chaining.

Example
# Line chart with map, defaulting to map view
Chart(df).mark_line().mark_map().show("map").encode(...)

# Line chart with customized map
Chart(df).mark_line().mark_map(
    color_scheme='Reds',
    binning_strategy='manual',
    custom_numeric_values=[0, 1000, 10000, 100000]
).encode(...)
Source code in owid/grapher/__init__.py
def mark_map(
    self,
    time_tolerance: Optional[int] = None,
    color_scheme: Optional[ColorSchemeName] = None,
    binning_strategy: Optional[BinningStrategy] = None,
    custom_numeric_values: Optional[List[float]] = None,
) -> "Chart":
    """Enable the map tab with optional configuration.

    Adds a world map visualization showing data geographically. Can be combined
    with other mark_*() methods.

    Args:
        time_tolerance: How many years to look back/forward for data
        color_scheme: Color scheme name (e.g., "Reds", "Blues", "YlOrRd")
        binning_strategy: How to bin values ("auto", "manual", "equalInterval", "quantiles")
        custom_numeric_values: Custom bin boundaries when using manual binning

    Returns:
        Self for method chaining.

    Example:
        ```python
        # Line chart with map, defaulting to map view
        Chart(df).mark_line().mark_map().show("map").encode(...)

        # Line chart with customized map
        Chart(df).mark_line().mark_map(
            color_scheme='Reds',
            binning_strategy='manual',
            custom_numeric_values=[0, 1000, 10000, 100000]
        ).encode(...)
        ```
    """
    self.config.has_map_tab = True

    # Set default tab to map if this is the first mark_*() call
    if self.default_tab is None:
        self.default_tab = "map"

    # Configure map options if any provided
    if any([time_tolerance, color_scheme, binning_strategy, custom_numeric_values]):
        color_scale = ColorScaleConfig(
            baseColorScheme=color_scheme,
            binningStrategy=binning_strategy,
            customNumericValues=custom_numeric_values,
        )
        self.config.map_config = MapConfig(
            timeTolerance=time_tolerance,
            colorScale=color_scale
            if any([color_scheme, binning_strategy, custom_numeric_values])
            else None,
        )

    return self

show

show(
    tab: Literal[
        "line",
        "discrete-bar",
        "stacked-discrete-bar",
        "scatter",
        "stacked-area",
        "slope",
        "stacked-bar",
        "marimekko",
        "map",
        "table",
    ],
) -> Chart

Set which tab to display by default.

Use this to control which visualization is shown when the chart first loads. The tab must correspond to an enabled chart type (via mark_*() methods).

PARAMETER DESCRIPTION
tab

The tab to show by default. Options: - "line": Line chart - "discrete-bar": Bar chart - "stacked-discrete-bar": Stacked bar chart - "scatter": Scatter plot - "map": World map - "table": Data table

TYPE: Literal['line', 'discrete-bar', 'stacked-discrete-bar', 'scatter', 'stacked-area', 'slope', 'stacked-bar', 'marimekko', 'map', 'table']

RETURNS DESCRIPTION
Chart

Self for method chaining.

Example
# Enable line and bar, but show bar by default
Chart(df).mark_line().mark_bar().show("discrete-bar").encode(...)
Source code in owid/grapher/__init__.py
def show(
    self,
    tab: Literal[
        "line",
        "discrete-bar",
        "stacked-discrete-bar",
        "scatter",
        "stacked-area",
        "slope",
        "stacked-bar",
        "marimekko",
        "map",
        "table",
    ],
) -> "Chart":
    """Set which tab to display by default.

    Use this to control which visualization is shown when the chart first loads.
    The tab must correspond to an enabled chart type (via mark_*() methods).

    Args:
        tab: The tab to show by default. Options:
            - "line": Line chart
            - "discrete-bar": Bar chart
            - "stacked-discrete-bar": Stacked bar chart
            - "scatter": Scatter plot
            - "map": World map
            - "table": Data table

    Returns:
        Self for method chaining.

    Example:
        ```python
        # Enable line and bar, but show bar by default
        Chart(df).mark_line().mark_bar().show("discrete-bar").encode(...)
        ```
    """
    self.default_tab = tab
    return self

interact

interact(
    allow_relative: Optional[bool] = None,
    scale_control: Optional[bool] = None,
    entity_control: Optional[bool] = None,
) -> Chart

Add interactive controls to the chart.

PARAMETER DESCRIPTION
allow_relative

Show relative/absolute toggle.

TYPE: Optional[bool] DEFAULT: None

scale_control

Show log/linear scale toggle.

TYPE: Optional[bool] DEFAULT: None

entity_control

Show entity/country picker.

TYPE: Optional[bool] DEFAULT: None

RETURNS DESCRIPTION
Chart

Self for method chaining.

Source code in owid/grapher/__init__.py
def interact(
    self,
    allow_relative: Optional[bool] = None,
    scale_control: Optional[bool] = None,
    entity_control: Optional[bool] = None,
) -> "Chart":
    """Add interactive controls to the chart.

    Args:
        allow_relative: Show relative/absolute toggle.
        scale_control: Show log/linear scale toggle.
        entity_control: Show entity/country picker.

    Returns:
        Self for method chaining.
    """
    if allow_relative is not None:
        self.config.hide_relative_toggle = False

    if scale_control is not None:
        # Update y_axis without overwriting existing settings
        self.config.y_axis["scaleType"] = "linear"
        self.config.y_axis["canChangeScaleType"] = scale_control

    if entity_control is not None:
        self.config.hide_entity_controls = not entity_control

    return self

select

select(
    entities: Optional[List[str]] = None,
    timespan: Optional[Tuple[Any, Any]] = None,
) -> Chart

Pre-select entities and time range.

PARAMETER DESCRIPTION
entities

List of entity names to display.

TYPE: Optional[List[str]] DEFAULT: None

timespan

Tuple of (start, end) for time range.

TYPE: Optional[Tuple[Any, Any]] DEFAULT: None

RETURNS DESCRIPTION
Chart

Self for method chaining.

Source code in owid/grapher/__init__.py
def select(
    self,
    entities: Optional[List[str]] = None,
    timespan: Optional[Tuple[Any, Any]] = None,
) -> "Chart":
    """Pre-select entities and time range.

    Args:
        entities: List of entity names to display.
        timespan: Tuple of (start, end) for time range.

    Returns:
        Self for method chaining.
    """
    if entities:
        self.selection = entities

    if timespan:
        if isinstance(timespan, (str, int)):
            timespan = (timespan, None)
        self.timespan = timespan

    return self

transform

transform(relative: bool) -> Chart

Transform data to relative or absolute values.

Display values as percentage change from a baseline (relative mode) or as absolute values (default). In relative mode, the first time period serves as the baseline (100%).

PARAMETER DESCRIPTION
relative

If True, show values as percentage change from baseline. If False, show absolute values.

TYPE: bool

RETURNS DESCRIPTION
Chart

Self for method chaining.

Source code in owid/grapher/__init__.py
def transform(self, relative: bool) -> "Chart":
    """Transform data to relative or absolute values.

    Display values as percentage change from a baseline (relative mode) or as
    absolute values (default). In relative mode, the first time period serves
    as the baseline (100%).

    Args:
        relative: If True, show values as percentage change from baseline.
            If False, show absolute values.

    Returns:
        Self for method chaining.
    """
    self.config.stack_mode = "relative" if relative else "absolute"
    return self

filter

filter(matching_entities_only: bool = True) -> Chart

Filter entities to only show those with complete data.

When enabled, only entities that have data for all time periods and dimensions will be shown. Useful for ensuring fair comparisons by excluding entities with incomplete data.

PARAMETER DESCRIPTION
matching_entities_only

If True, only show entities with complete data across all dimensions and time periods. If False, show all entities even with gaps.

TYPE: bool DEFAULT: True

RETURNS DESCRIPTION
Chart

Self for method chaining.

Source code in owid/grapher/__init__.py
def filter(self, matching_entities_only: bool = True) -> "Chart":
    """Filter entities to only show those with complete data.

    When enabled, only entities that have data for all time periods and dimensions
    will be shown. Useful for ensuring fair comparisons by excluding entities with
    incomplete data.

    Args:
        matching_entities_only: If True, only show entities with complete data across
            all dimensions and time periods. If False, show all entities even with gaps.

    Returns:
        Self for method chaining.
    """
    self.config.matching_entities_only = matching_entities_only
    return self

variable

variable(
    column: str,
    name: Optional[str] = None,
    description_short: Optional[str] = None,
    description_from_producer: Optional[str] = None,
    description_processing: Optional[str] = None,
    description_key: Optional[List[str]] = None,
    unit: Optional[str] = None,
    short_unit: Optional[str] = None,
    source_name: Optional[str] = None,
    source_link: Optional[str] = None,
) -> Chart

Add rich metadata to a data column/variable.

Configures display properties and documentation for a column that will appear in tooltips, the data table, and source information.

PARAMETER DESCRIPTION
column

Name of the DataFrame column to configure.

TYPE: str

name

Display name (e.g., "Population" instead of "pop").

TYPE: Optional[str] DEFAULT: None

description_short

Brief description shown in tooltips.

TYPE: Optional[str] DEFAULT: None

description_from_producer

Original description from data source.

TYPE: Optional[str] DEFAULT: None

description_processing

How the data was processed/transformed.

TYPE: Optional[str] DEFAULT: None

description_key

List of key points about the variable.

TYPE: Optional[List[str]] DEFAULT: None

unit

Full unit name (e.g., "million people").

TYPE: Optional[str] DEFAULT: None

short_unit

Abbreviated unit for compact display (e.g., "M").

TYPE: Optional[str] DEFAULT: None

source_name

Name of the data source.

TYPE: Optional[str] DEFAULT: None

source_link

URL to the data source.

TYPE: Optional[str] DEFAULT: None

RETURNS DESCRIPTION
Chart

Self for method chaining.

Note

The timespan is computed automatically from the data's time column.

Example
Chart(df).mark_line().encode(
    x='year',
    y='population',
    entity='country'
).variable(
    'population',
    name='Population',
    description_short='Total population in millions',
    unit='million people',
    short_unit='M',
    source_name='World Bank',
    source_link='https://data.worldbank.org'
)
Source code in owid/grapher/__init__.py
def variable(
    self,
    column: str,
    name: Optional[str] = None,
    description_short: Optional[str] = None,
    description_from_producer: Optional[str] = None,
    description_processing: Optional[str] = None,
    description_key: Optional[List[str]] = None,
    unit: Optional[str] = None,
    short_unit: Optional[str] = None,
    source_name: Optional[str] = None,
    source_link: Optional[str] = None,
) -> "Chart":
    """Add rich metadata to a data column/variable.

    Configures display properties and documentation for a column that will
    appear in tooltips, the data table, and source information.

    Args:
        column: Name of the DataFrame column to configure.
        name: Display name (e.g., "Population" instead of "pop").
        description_short: Brief description shown in tooltips.
        description_from_producer: Original description from data source.
        description_processing: How the data was processed/transformed.
        description_key: List of key points about the variable.
        unit: Full unit name (e.g., "million people").
        short_unit: Abbreviated unit for compact display (e.g., "M").
        source_name: Name of the data source.
        source_link: URL to the data source.

    Returns:
        Self for method chaining.

    Note:
        The timespan is computed automatically from the data's time column.

    Example:
        ```python
        Chart(df).mark_line().encode(
            x='year',
            y='population',
            entity='country'
        ).variable(
            'population',
            name='Population',
            description_short='Total population in millions',
            unit='million people',
            short_unit='M',
            source_name='World Bank',
            source_link='https://data.worldbank.org'
        )
        ```
    """
    self.variable_configs[column] = VariableConfig(
        name=name,
        description_short=description_short,
        description_from_producer=description_from_producer,
        description_processing=description_processing,
        description_key=description_key,
        unit=unit,
        short_unit=short_unit,
        source_name=source_name,
        source_link=source_link,
    )
    return self

export

export(include_data: bool = True) -> Dict[str, Any]

Export the chart configuration as a dictionary.

PARAMETER DESCRIPTION
include_data

If True, includes the data in the export.

TYPE: bool DEFAULT: True

RETURNS DESCRIPTION
Dict[str, Any]

Dictionary containing the full chart configuration.

Source code in owid/grapher/__init__.py
def export(self, include_data: bool = True) -> Dict[str, Any]:
    """Export the chart configuration as a dictionary.

    Args:
        include_data: If True, includes the data in the export.

    Returns:
        Dictionary containing the full chart configuration.
    """
    config = self.config.to_dict()  # type: ignore

    # Add chart types and tab
    chart_types = self.chart_types if self.chart_types else ["LineChart"]
    config["chartTypes"] = chart_types

    # Set tab based on default_tab or first chart type
    if self.default_tab:
        config["tab"] = self.default_tab
    elif chart_types:
        config["tab"] = _CHART_TYPE_TO_TAB.get(chart_types[0], "line")

    # Auto-improve: show title annotation for line charts with titles
    if self.config.title and "LineChart" in chart_types:
        config["hideTitleAnnotation"] = False

    # Convert MapConfig to dict (dataclass_json doesn't handle it automatically)
    if self.config.map_config is not None:
        config["mapConfig"] = self.config.map_config.to_dict()

    primary_type = self._get_primary_chart_type()
    config.update(self.data_config().to_dict(primary_type))
    config = prune(config)
    if not include_data:
        del config["owidDataset"]["data"]
    return config

owid.grapher.ChartConfig dataclass

ChartConfig(
    title: str = "",
    subtitle: str = "",
    note: str = "",
    source_desc: str = "",
    hide_logo: bool = True,
    is_published: bool = True,
    hide_title_annotation: bool = True,
    hide_legend: bool = False,
    hide_entity_controls: bool = True,
    hide_relative_toggle: bool = True,
    has_map_tab: bool = False,
    map_config: Optional[MapConfig] = None,
    stack_mode: Literal[
        "relative", "absolute"
    ] = "absolute",
    matching_entities_only: bool = False,
    x_axis: dict = dict(),
    y_axis: dict = dict(),
)

Configuration for OWID chart display and behavior.

This dataclass holds all chart-level settings including title, subtitle, axis configuration, and UI control visibility. Properties use snake_case in Python but are automatically converted to camelCase for the JavaScript Grapher library.

Note: Chart types are now managed by the Chart class via chart_types list, not in this config class.

ATTRIBUTE DESCRIPTION
title

Main chart title.

TYPE: str

subtitle

Additional context below title.

TYPE: str

note

Footnote text displayed at bottom.

TYPE: str

source_desc

Data source attribution.

TYPE: str

hide_logo

If True, hides OWID logo (default for embedded charts).

TYPE: bool

is_published

Publication status flag.

TYPE: bool

hide_title_annotation

If True, hides the annotation arrow on title.

TYPE: bool

hide_legend

If True, hides the chart legend.

TYPE: bool

hide_entity_controls

If True, hides the entity/country picker UI.

TYPE: bool

hide_relative_toggle

If True, hides relative/absolute toggle button.

TYPE: bool

has_map_tab

If True, enables the map visualization tab.

TYPE: bool

stack_mode

For stacked charts, 'absolute' or 'relative' (percentage).

TYPE: Literal['relative', 'absolute']

matching_entities_only

If True, only show entities with complete data.

TYPE: bool

x_axis

Dictionary of x-axis configuration (label, scale, etc).

TYPE: dict

y_axis

Dictionary of y-axis configuration (label, scale, etc).

TYPE: dict

owid.grapher.Dimension dataclass

Dimension(
    property: Literal["y", "x", "color"],
    variable_name: str,
    display: Optional[dict] = dict(),
)

Maps a DataFrame column to a chart dimension.

Dimensions define how data columns are used in the chart visualization. Each dimension specifies a visual property (x, y, color) and the source column name, along with optional display settings.

ATTRIBUTE DESCRIPTION
property

The visual property this dimension controls ('y' for y-axis, 'x' for x-axis, 'color' for color encoding).

TYPE: Literal['y', 'x', 'color']

variable_name

Name of the column from the DataFrame to use for this dimension.

TYPE: str

display

Optional dictionary of display settings (e.g., {'unit': '$', 'numDecimalPlaces': 2}).

TYPE: Optional[dict]

Example
Dimension(
    property="y",
    variable_name="population",
    display={"unit": "people", "numDecimalPlaces": 0}
)

owid.grapher.TimeType

Bases: Enum

Enumeration for time dimension types.

Determines how time values are interpreted and displayed in charts.

ATTRIBUTE DESCRIPTION
DAY

Daily or date-based data. Automatically detected when x='date'. Uses ISO date format (YYYY-MM-DD).

YEAR

Annual data (default). Standard yearly time series.