Export, accessibility & small-multiple dashboards

A chart that looks fine in a notebook can turn blurry in a PDF, unreadable on a phone, or meaningless to a colour-blind manager. This lesson covers the final mile: exporting, accessibility and arranging many charts as one dashboard.

Saving for the right destination

fig.savefig("sales.png", dpi=200, bbox_inches="tight")       # slides, WhatsApp, email
fig.savefig("sales.svg", bbox_inches="tight")                # web pages, crisp at any zoom
fig.savefig("sales.pdf", bbox_inches="tight")                # printed reports, LaTeX
fig.savefig("sales_web.png", dpi=110, transparent=True)      # dark or light site themes
Format Type Best for
PNG Raster Slides, chat apps, email
SVG Vector Websites, further editing in Figma/Inkscape
PDF Vector Print and reports
JPG Lossy raster Avoid - blurs text and lines

bbox_inches="tight" trims white space so labels are not cut off. Set figsize to the real size you will display (in inches) before plotting; scaling an image later changes font sizes unpredictably.

In a Django view, render into memory rather than disk:

import io
import matplotlib
matplotlib.use("Agg")                  # non-GUI backend for servers
import matplotlib.pyplot as plt

def chart_png(values):
    fig, ax = plt.subplots(figsize=(6, 3))
    ax.plot(values)
    buf = io.BytesIO()
    fig.savefig(buf, format="png", dpi=150, bbox_inches="tight")
    plt.close(fig)                      # free memory on every request
    return buf.getvalue()

Accessible colour and design

About 1 in 12 men have some colour vision deficiency, so red-versus-green alone is a poor way to show profit and loss.

  • Use tested palettes: plt.style.use("tableau-colorblind10"), seaborn's "colorblind", or viridis/cividis for continuous data.
  • Add a second channel besides colour: markers, line styles, or direct labels.
  • Keep text at least 9-10 pt at final size and ensure strong contrast against the background.
  • Use grey for context and one strong colour for the series you want readers to notice.
  • For web images, write meaningful alt text such as "Line chart: Pune sales rose 18% from April to October".

Small multiples

When comparing many categories, one crowded chart with ten coloured lines fails. Small multiples - a grid of identical mini-charts with shared axes - let the eye compare shapes instantly.

import numpy as np
import pandas as pd

rng = np.random.default_rng(3)
months = pd.date_range("2025-04-01", periods=12, freq="MS")
cities = ["Pune", "Nagpur", "Nashik", "Thane", "Aurangabad", "Kolhapur"]
data = {c: 50 + rng.normal(0, 6, 12).cumsum() for c in cities}

fig, axes = plt.subplots(2, 3, figsize=(10, 5), sharex=True, sharey=True)
for ax, city in zip(axes.flat, cities):
    for other in cities:                          # faint context lines
        ax.plot(months, data[other], color="0.85", lw=1)
    ax.plot(months, data[city], color="#1f5fa8", lw=2)
    ax.set_title(city, fontsize=10, loc="left")
    ax.spines[["top", "right"]].set_visible(False)
fig.suptitle("Monthly sales (lakh INR): each branch vs the rest", x=0.01, ha="left")
fig.autofmt_xdate()
fig.tight_layout()

sharey=True is essential: without a common scale, panels look similar even when values differ tenfold.

Key takeaways

  • Choose the format by destination: SVG/PDF for vectors, PNG at a known DPI for everything else.
  • Always plt.close(fig) in loops and web views.
  • Never rely on colour alone; pick colour-blind-safe palettes.
  • Small multiples with shared axes beat spaghetti charts.

Practice

Build a 3x3 small-multiple dashboard of weekly orders for nine sweet-shop outlets using a colour-blind-safe colour, highlight each outlet against grey context lines, and save it as both SVG and 200-DPI PNG. Write one sentence of alt text describing the main pattern.

B

Written by Bablu Kumar Jha

Founder, BeeProton AI · Mumbai, Maharashtra, India