Making Altair/Vega-Lite charts readable without squinting

My love for the Grammar of Graphics runs deep, and in particular for Hadley Wickham’s famous ggplot2 which showed me the light back when I was a young PhD student. Seriously, once you have your head around how it works it gives you datavis superpowers. These days I often work in Python, and for datavis I’m enjoying Altair which is based around the same philosophy (and outputs to Vega-Lite for rendering in the browser).

Recently I’ve needed to (a) create some snazzy graphs with Altair and (b) display them in a slide deck. Part (a) was actually the easy part—the tricky part was (b) getting Altair to render charts with text & other marks that weren’t so small that the slide was unreadable.

Here’s an example: a simple line chart from the Altair Example Gallery.

import altair as alt
import numpy as np
import pandas as pd

x = np.arange(100)
source = pd.DataFrame({"x": x, "f(x)": np.sin(x / 5)})

alt.Chart(source).mark_line().encode(x="x", y="f(x)").save(f"{CHART_DIR}/sin-x.svg")

which (with default settings) produces a chart that looks like this:

f(x) = sin(x)/5

Easy tweaking of “size” through chart themes

Now, that figure might look fairly readable, but when it’s on a slide the text, labels & even lines are quite small1. I don’t need fine-grained control over the relative sizes of labels vs legend vs title, etc. I just want a simple knob for making all the text bigger so that my slides don’t double as an eye chart. The Vega-Lite folks (the underlying vis engine which Altair uses) know about the issue, but don’t want to fix it.

Note that when I’m talking about “size” I’m not talking about the size & dimensions of the chart—I’m talking about the size of the text, lines & other marks relative to the overall size of the chart.

The easiest way I found to fix this is to set a small width & height for the chart, then export to a vector format (e.g. svg) so that when the image gets displayed everything will be “stretched” up into big, bold sizes (and since it’s a vector format, things will still be nice and crisp). This chart code is the same except for the .properties(width=100, height=60) part:

alt.Chart(source).mark_line().encode(x="x", y="f(x)").properties(
    width=100, height=60
).save(f"{CHART_DIR}/sin-x-big-text.svg")

f(x) = sin(x)/5 with bigger labels

Obviously I’m exaggerating here to make a point, but the key point is that there are just a couple of numbers to tweak (width and height) which control text & line size, label sizes, and also titles and legends (if present). And that’s not something that’s exposed as simply in any other way by the Altair/Vega-Lite API.

One final tip: if you want to have consistent sizes & aspect ratios across lots of charts (e.g. you’re batch exporting lots of charts for a presentation or report) you can create a custom theme, but otherwise you can just do it with a call to the .properties() method as shown.

  1. To be honest, these simple examples from the example gallery don’t really help me make my point, they’re still pretty readable. But when the charts get more complicated & have more data marks then things get smaller & more zoomed out, and the problem gets much worse.