Making Altair/Vega-Lite charts readable without squinting

Ben Swift October 16, 2019
Source

title: "Making Altair/Vega-Lite charts readable without squinting" description: "A simple trick for making Altair chart text and marks bigger: set a small width/height and export to SVG." tags: - dev

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 small[^examples]. 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.

:::info

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.

[^examples]: 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.

Discussion in the ATmosphere

Loading comments...