3  Using the package with Plotly

3.1 Line charts

3.1.1 Single line chart

import plotly.express as px
import plotly.graph_objects as go

from afcharts.pio_template import pio

# Set default theme
pio.templates.default = "afcharts"

# Load the gapminder dataset from plotly.express
df = px.data.gapminder()
df = df[df["country"] == "United Kingdom"]

# Create figure
fig = go.Figure()

# Add a trace
fig.add_trace(
    go.Scatter(
        x=df["year"],
        y=df["lifeExp"],
        mode="lines",
        name="United Kingdom",
        text=df["country"],
    )
)

# Add label at the last point
last_year = df["year"].max()
last_lifeExp = df[df["year"] == last_year]["lifeExp"].values[0]

# Update layout
fig.update_layout(
    xaxis=dict(
        showgrid=False,  # Hide x-axis grid lines
        dtick=10,  # Show ticks every 10 units
        range=[1950, 2010],
    ),
    yaxis=dict(
        range=[0, 82],
        tickmode="linear",
        dtick=10,  # Show ticks every 10 units
    ),
    showlegend=False,
    height=400,
    margin=dict(r=40),
)

fig.show()
Living Longer
Life Expectancy in the United Kingdom 1952-2007
Source: Gapminder

This line chart uses the afcharts theme. There are pale grey grid lines extending from the y axis, and there is a thicker dark blue line representing the data.

3.1.2 Line chart with duo palette

import plotly.express as px
import plotly.graph_objects as go

from afcharts.pio_template import pio
from afcharts.af_colours import get_af_colours

# Set default theme
pio.templates.default = "afcharts"

# Get the duo colour palette
duo = get_af_colours("duo")

# Load the gapminder dataset from plotly.express
df = px.data.gapminder()
df = df[df["country"].isin(["United Kingdom", "China"])]

# Create figure
fig = go.Figure()

# Add a trace for each continent
for i, country in enumerate(df["country"].unique()):
    df_country = df[df["country"] == country]

    fig.add_trace(
        go.Scatter(
            x=df_country["year"],
            y=df_country["lifeExp"],
            mode="lines",
            name=country,
            text=df_country["country"],
            line=dict(color=duo[i % len(duo)]),
        )
    )

    # Add label at the last point
    last_year = df_country["year"].max()
    last_lifeExp = df_country[df_country["year"] == last_year]["lifeExp"].values[0]

    fig.add_annotation(
        dict(
            x=last_year,
            y=last_lifeExp,
            text=country,
            showarrow=False,
            xanchor="left",
            yanchor="middle",
            bgcolor="white",  # Add a white background
        )
    )

# Update layout
fig.update_layout(
    xaxis=dict(
        showgrid=False,  # Hide x-axis grid lines
        dtick=10,  # Show ticks every 10 units
        range=[1950, 2010],
    ),
    yaxis=dict(
        range=[0, 82],
        tickmode="linear",
        dtick=10,  # Show ticks every 10 units
    ),
    showlegend=False,
    height=350,
    margin=dict(r=120),
)

fig.show()
Living Longer
Life Expectancy in the United Kingdom and China 1952-2007
Source: Gapminder

This line chart uses the afcharts theme and there are thin pale grey lines extending from the y axis. There are two thicker lines showing the life expectancy in the UK and China over time. The line colours are from the main Analysis Function palette - dark blue for China and orange for the UK, with labels for each line on the right hand side.

Legends should be avoided unless absolutely necessary, as these usually rely on using colour to match labels to data. More information can be found in the Analysis Function charts guidance. It is best practice to label lines directly.

3.2 Bar charts

import plotly.express as px
import plotly.graph_objects as go

from afcharts.pio_template import pio

# Set default theme
pio.templates.default = "afcharts"

# Load the gapminder dataset from plotly.express
df = px.data.gapminder().query("year == 2007 & continent == 'Americas'")

top5 = df.nlargest(5, "pop")
fig = go.Figure()

fig.add_trace(
    go.Bar(
        x=top5["country"],
        y=top5["pop"]/1e6,  # Convert to millions

    )
)

# Update layout
fig.update_layout(
    height=420
)

fig.show()
The U.S.A. is the most populous country in the Americas
Population of countries in the Americas (millions), 2007
Source: Gapminder

This bar chart uses the afcharts theme, and shows the populations of the five most populous countries in the Americas. Each bar is dark blue and labelled by country underneath. All text is black in a sans serif font. Pale grey grid lines extend out from the y axis.

3.2.1 Grouped bar chart

import plotly.express as px
import plotly.graph_objects as go

from afcharts.pio_template import pio
from afcharts.af_colours import get_af_colours

# Set default theme
pio.templates.default = "afcharts"

# Get the duo colour palette
duo = get_af_colours("duo")

# Load the gapminder dataset from plotly.express
df = px.data.gapminder().query(
    "year in [1967, 2007] & country in ['United Kingdom', 'Ireland', 'France', 'Belgium']"
)

fig = go.Figure()
# Add a bar trace for each year
for i, year in enumerate(sorted(df["year"].unique())):
    df_year = df[df["year"] == year]
    fig.add_trace(
        go.Bar(
            x=df_year["country"],
            y=df_year["lifeExp"],
            name=str(year),
            marker_color=duo[i % len(duo)],
        )
    )

# Update layout
fig.update_layout(
    barmode='group',
    height=420,
    legend=dict(
        orientation="h",
        yanchor="top",
        y=-0.2,
        xanchor="center",
        x=0.5
    ),
)

fig.show()
Living longer
Life expectancy (years) in 1967 and 2007
Source: Gapminder

This grouped bar chart uses the afcharts theme. It shows the life expectancy in 1967 and 2007 for four countries, which are displayed on the x axis. For each country there are two bars. The bar colours are from the main Analysis Function palette - dark blue for 1967 and orange for 2007, denoted by a legend at the bottom of the chart.

3.2.2 Stacked bar chart

Caution should be taken when producing stacked bar charts. They can quickly become difficult to interpret if plotting non part-to-whole data, and/or if plotting more than two categories per stack. First and last categories in the stack will always be easier to compare across bars than those in the middle. Think carefully about the story you are trying to tell with your chart.

import pandas as pd
import plotly.express as px
import plotly.graph_objects as go

from afcharts.pio_template import pio
from afcharts.af_colours import get_af_colours

# Set default theme
pio.templates.default = "afcharts"

# Get the duo colour palette
duo = get_af_colours("duo")

# Load the gapminder dataset from plotly.express
df = px.data.gapminder().query("year == 2007")

# Create life expectancy groups
df['lifeExpGrouped'] = pd.cut(
    df['lifeExp'],
    bins=[0, 75, float('inf')],
    labels=["Under 75", "75 and over"]
)

# Group by continent and life expectancy group
grouped = (
    df.groupby(["continent", "lifeExpGrouped"], observed=True)
    .size()
    .reset_index(name="n_countries")
)

# Pivot to get proportions
pivot_df = grouped.pivot(
    index="continent", columns="lifeExpGrouped", values="n_countries"
).fillna(0)
pivot_df["total"] = pivot_df.sum(axis=1)
pivot_df["percent of Under 75"] = pivot_df["Under 75"] / pivot_df["total"]
pivot_df["percent of 75 and over"] = pivot_df["75 and over"] / pivot_df["total"]

categories = ["Under 75", "75 and over"]

fig = go.Figure()

# Add a bar trace for each category
for i, category in enumerate(categories):
    percent_col = f"percent of {category}"
    life_exp_data = pivot_df[[percent_col]]

    fig.add_trace(
        go.Bar(
            x=life_exp_data.index,
            y=life_exp_data[percent_col],
            name=str(category),
            marker_color=duo[i % len(duo)],
        )
    )

# Update layout
fig.update_layout(
    barmode="stack",
    height=420,
    yaxis=dict(tickformat=".0%"),
    legend=dict(
        title="Life Expectancy",
        orientation="h",
        yanchor="top",
        y=-0.2,
        xanchor="center",
        x=0.5,
    ),
)

fig.show()
How life expectancy varies
Distribution of life expectancy, 2007
Source: Gapminder

This histogram uses the afcharts theme, and shows the distribution of life expectancy by number of countries. There are pale grey grid lines extending out from the y axis. The bars are dark blue with white space between each.

3.3 Scatterplots

import plotly.express as px
import plotly.graph_objects as go

from afcharts.pio_template import pio

# Set default theme
pio.templates.default = "afcharts"

# Load the gapminder dataset from plotly.express
df = px.data.gapminder()

df = df.query("year == 2007")

fig = go.Figure()

fig.add_trace(
    go.Scatter(
        x=df["gdpPercap"],
        y=df["lifeExp"],
        mode="markers",
    )
)

# Axes should start from 0
fig.update_yaxes(rangemode="tozero")

# Update layout
fig.update_layout(
    xaxis=dict(
        title="GDP per capita ($US, inflation-adjusted)",
    ),
    yaxis=dict(title="Life Expectancy (years)"),
    height=420,
)

fig.show()
The relationship between GDP and Life Expectancy is complex
GDP and Life Expectancy for all countries, 2007
Source: Gapminder

This scatterplot uses the afcharts theme, and shows life expectancy against GDP per capita for 142 countries in 2007. Thin pale grey lines extend out from the x and y axis labels, forming a grid. The data points are plotted as dark blue circles. Both axes are labeled in black using a sans serif font.

3.4 Small multiples

import plotly.express as px
import plotly.graph_objects as go
from plotly.subplots import make_subplots

from afcharts.af_colours import get_af_colours
from afcharts.pio_template import pio

# Set default theme
pio.templates.default = "afcharts"

# Load the gapminder dataset from plotly.express
df = px.data.gapminder()

# Get the categorical colour palette
categorical = get_af_colours("categorical")

# Filter out Oceania and aggregate population by continent and year
df_filtered = df[df["continent"] != "Oceania"]
df_grouped = (
    df_filtered.groupby(["continent", "year"], observed=True)["pop"].sum().reset_index()
)

# Define the continents to plot
continents = df_grouped["continent"].unique()

# Create a 2x2 subplot layout
fig = make_subplots(rows=2, cols=2, subplot_titles=continents, shared_yaxes=True)

# Add area traces for each continent
for i, continent in enumerate(continents):
    row = i // 2 + 1
    col = i % 2 + 1
    data = df_grouped[df_grouped["continent"] == continent]
    fig.add_trace(
        go.Scatter(
            x=data["year"],
            y=data["pop"],
            fill="tozeroy",
            mode="none",
            name=continent,
            showlegend=False,
            fillcolor=categorical[i % len(categorical)],
        ),
        row=row,
        col=col,
    )


# Customize axes
fig.update_xaxes(showgrid=False)
fig.update_yaxes(
    range=[0, 4.1e9],
    tickvals=[0, 2e9, 4e9],
    ticktext=["0", "2bn", "4bn"],
    showgrid=True,
)

# Update layout
fig.update_layout(
    height=550,
    margin=dict(t=30),
    )

fig.show()
Asia’s rapid growth
Population growth by continent, 1952-2007
Source: Gapminder

This chart uses the afcharts theme. It contains four subplots in a two by two grid showing how the populations of four continents have changed over time. Each subplot is labelled with the continent. The subplots have a common y axis, with no values on the x axis to facilitate for a simple comparison of the relative values. Each subplot is filled with a different colour from the Analysis Function categorical colour palette to be distinct from other subplots.

3.5 Pie charts

import pandas as pd
import plotly.express as px
import plotly.graph_objects as go

from afcharts.af_colours import get_af_colours
from afcharts.pio_template import pio

# Set default theme
pio.templates.default = "afcharts"

# Get the duo colour palette
duo = get_af_colours("duo")

# Load the gapminder dataset from plotly.express
df = px.data.gapminder().query("continent == 'Europe' and year == 2007")

# Create life expectancy groups
df['lifeExpGrouped'] = pd.cut(
    df['lifeExp'],
    bins=[0, 75, float('inf')],
    labels=["Under 75", "75 and over"]
)

# Count number of countries in each group
group_counts = df["lifeExpGrouped"].value_counts().sort_index()

fig = go.Figure(
    data=[go.Pie(
        labels=group_counts.index,
        values=group_counts.values,
        marker=dict(colors=duo, line=dict(color='white', width=2)),
        sort=False,
        textinfo='label+percent',
        textposition='inside',
        texttemplate='%{label}<br>(%{percent:.0%})'
    )]
)

# Update layout
fig.update_layout(
    height=400,
    showlegend=False
)

fig.show()
How life expectancy varies in Europe
Percentage of countries by life expectancy band, 2007
Source: Gapminder

This pie chart uses the afcharts theme, showing the proportions of European countries with a life expectancy under and over 75. The segment colours are from the Analysis Function categorical palette, with the smaller under 75 segment in dark blue, and the larger over 75 segment in orange. This is indicated by a legend to the right of the pie chart. There is whitespace separating the segments from each other.

3.6 Focus charts

import plotly.express as px
import plotly.graph_objects as go

from afcharts.af_colours import get_af_colours
from afcharts.pio_template import pio

# Get the focus colour palette
focus = get_af_colours("focus")

# Set default theme
pio.templates.default = "afcharts"

# Load the gapminder dataset from plotly.express
df = px.data.gapminder().query("year == 2007 & continent == 'Americas'")

top5 = df.nlargest(5, "pop")

colors = {}
for country in top5["country"].unique():
    colors[country] = focus[0] if country == "Brazil" else focus[1]

# Map colors to bar order
bar_colors = [colors[country] for country in top5["country"]]

fig = go.Figure()

fig.add_trace(
    go.Bar(
        x=top5["country"],
        y=top5["pop"],  # Repeat the category name for each x value
        marker_color=bar_colors,
    )
)

# Update layout
fig.update_layout(
    height=420
)

fig.show()
Brazil has the second highest population in the Americas
Population of countries in the Americas (millions), 2007
Source: Gapminder

This bar chart uses the afcharts theme, and shows the populations of five countries of the Americas in descending order. The country names are given on the x axis, with all chart text in black in a sans serif font. Four of the bars on the chart are light grey, and the bar for Brazil is filled in dark blue to highlight it.