Background
The line plot is one of the simplest charts you’ll come across in practice but that doesn’t mean that it isn’t a powerful tool for visualising information!
I’ve come across a few resources in the past (including an actuarial exam on professional communication, as fun as it sounds) which have tried to lay out best practice for line plots. Unfortunately – like many intersections of theory and reality – these guidelines are not always applicable.
Now, I love a line plot and I’d go as far as saying it’s my favourite kind of plot to create. Nerdy, I know.
I’ve picked up a few tricks along the way which I’ll share below.
When to use?
Line plots are best used in the following circumstances:
- When the quantity being charted (i.e. what’s being shown on the y-axis) is numeric.
- When the goal of the chart is to communicate a change or trend across some feature – e.g. time.
- When the feature being used to differentiate the target quantity (i.e. what’s being shown on the x-axis) is not overly granular, or can be transformed such that it is not overly granular.
- When the feature being used to differentiate the target quantity has some sort of ordering or progression to it (ideal rather than compulsory!).
Let’s get cracking!
That’s enough theory for now – time for some action.
We’ll start with a real example of a plot, discuss what we don’t like about it, and build up our code until we have a great visualisation.
Disclaimer: all the plots are created in the Matplotlib
Python library. Yes, the same plots could be created using seaborn
‘s simple interface. No, that doesn’t mean that you don’t need to know the matplotlib
basics.
Disclaimer (2): I’m an actuary, not a graphic designer… please bear that in mind when you see my colour choices!
Disclaimer (3): I’m not going to go into too much technical detail, although I will share my code. If you’re curious about all of the chart potential available in matplotlib
, take a look at the official documentation: matplotlib.pyplot.plot – Matplotlib 3.4.3 documentation
The base plot
Let’s plot a simple line plot of stock price and a smoothed version of the stock price.
It’s a simple bit of code:
And it produces a simple line plot:
That’s fairly simple – two lines of code gets you a basic plot. If you don’t mind the memory address for the object being shown, you can even do this in one line!
Fine, but this chart isn’t exactly pleasing to the eye and doesn’t really tell a story.
- It’s very small – we should make it easy to see.
- There’s no telling what this is trying to measure – we should make it easy to understand.
- It’s difficult to read values off the chart and to understand what is being represented – we should make it clear.
- I’m not a fan of the colours – we should make it good looking.
- It doesn’t necessarily convey the exact message we want to communicate – we should make it tell a story.
Let’s fix that, one step at a time!
Making it easy to see: changing the chart size
There are many ways of doing this.
I prefer to use the fig, ax = plt.subplots()
approach like many other Python users. This gives us loads of flexibility, especially when we work with seaborn
.
plt.subplots()
takes a figsize
argument which allows us to set the size of the chart. I like my charts rectangular and wider than they are tall, finding that this makes it easier to see on a screen.
Top tip #1: play around with this and see if there’s a size range that tickles your fancy.
Results in:
Much better!
Making it easy to understand: adding labels and a title
I’m always surprised to see how much more information a chart can convey when it has appropriate axis labels and titles.
These are straightforward to do using the set_xlabel()
, set_ylabel()
, set_title()
methods.
Let’s take a look:
Relatively small changes, but we can now quite easily see:
- What we’re trying to communicate (i.e. "Daily Closing Share Price (USD): 2010–2013").
- The units we’re measuring in, on the y-axis (i.e. "Closing Share Price (USD)").
- What we’re differentiating across on the x-axis (i.e. "Date").
Our chart is starting to look quite good, but it’s still quite difficult to read values off of the chart, not to mention that it’s quite difficult to understand what exactly the lines mean! Let’s fix that.
Making it clear: adding grid lines and a legend
For me, not including grid lines on a chart is a sin. Strong words, but it saves me from having to use a physical ruler on my computer screen (yes, I’ve actually done that).
Likewise, any chart with more than one quantity being visualised absolutely needs a legend. It’s crucial to know what is being plotted and how each quantity is being represented.
It’s quite easy to add in grid lines and legends using the grid()
and legend()
methods – let’s see them in action.
Top tip #2: grid lines shouldn’t distract the viewer from what’s actually being charted. Use the alpha
parameter to tone down the grid lines.
Top tip #3: legends can be placed in a variety of locations, both within and without the chart itself. Check out the loc
and bbox_to_anchor
parameters.
Now we’re getting somewhere! Let’s make a few aesthetic changes – I’m not a fan of the base theme.
Making it good looking: applying some style
Although our chart is starting to look quite good, it’s arguably quite bland and doesn’t really distinguish itself from the many other charts floating around.
It’s a good idea to put your personal – or company – stamp on your charts. Let’s do this now.
Top tip #4: many companies have a style guide specifying (among other things) font styles and graphic colour palettes. Use this to your advantage to create more distinguished visuals.
Let’s imagine that the company I work for uses a dark green theme. How could we incorporate this into the plot?
- I’ll plot the company share price in dark green – quite a nice link.
- The smoothed share price is currently plotted in orange. I’m not a fan of the dark green and orange combination, so I’ll change this to something that stands out against the green; red usually does the trick.
- I don’t like to show inferred or projected values using solid lines. I feel that this conveys that these are concrete facts, which in most cases is not really true. To this end, I’ll plot the smoothed share price using a dashed line.
Not too shabby! A few things to note:
- I’ve used the
linewidth
arguments to control how thick each of the lines are. It’s a good idea to play around with this, depending on what what exactly you would like to emphasise. - The
linestyle
parameter controls the type of line being plotted. There are multiple options available – take a look at the docs for more information.
So far, so good. But we still have a bit of a problem with this chart – it doesn’t really convey the message we want to communicate. Let’s rectify that.
Make it tell a story: using the chart title, additional graphics, and chart text
We’ll do exactly that – brace yourself for a chunk of code:
Which gives us:
What have we done?
- We’ve used the chart title to explicitly convey the message we want to communicate.
- Coloured boxes draw the viewers attention to certain areas of concern (do this with
axvspan()
). - Appropriately coloured (and placed) text messages give greater context to the shaded areas (do this with
text()
).
Wrapping up
… and rambling on a bit.
Line plots are a great tool for displaying numeric trends or relationships across some distinguishing feature. They are straightforward to create in matplotlib
, with tons of customisation available.
We’ve seen a good example of a bad chart and how to correct faults. In particular, we changed:
- chart size
- labels and titles
- legends
- colours and themes.
We briefly touched on how we could explicitly convey a message to viewers. We did this by using the chart title effectively and by adding additional graphics and text messages to the chart. I would highly recommend this, especially if your audience is not familiar with the topic at hand, or if the trend or relationship being visualised is not immediately apparent.
As I mentioned, I love a good line chart. Creating good line plots takes practice and I’d encourage you to try a few different things always keeping the question of "Does this chart communicate the message?" at heart.