Visualising data with Python's pyplot: a practical starter guide
Data surrounds us in everyday life, from the hourly temperature swings along Sydney harbour to the monthly coffee spend of a remote worker in Adelaide. Translating raw rows and columns into a picture that your eyes can scan in seconds is what makes data analysis genuinely useful, whether you are a student in Brisbane writing your first assignment or a junior analyst at a Melbourne fintech preparing a board update.
Python's pyplot module, which sits inside the popular matplotlib library, is the friendliest entry point for anyone who wants to draw a chart without wrestling with a steep learning curve. It follows a state-based interface where each call to a function modifies the current figure, much like building a picture by adding one layer at a time. The result is a tool that feels familiar to anyone who has used Excel, while still being powerful enough to publish alongside a research paper.
Because the broader matplotlib ecosystem is open source and free, Australian developers can use it without the licensing concerns that sometimes come with proprietary analytics suites. Whether you are prototyping a chart on a train between Parramatta and Central, or running a script on a university workstation in Perth, the same code runs on Windows, macOS and Linux. That portability explains why pyplot is a default fixture in introductory courses at universities such as UNSW and the University of Melbourne.
The aim of this guide is to walk through the essential pyplot building blocks, then combine them into a small repertoire of plots that you can adapt to your own datasets. You will not need prior plotting experience, only a working Python installation and a curious mindset. By the end, you should feel confident enough to draw a line chart, a scatter plot, a bar chart and a histogram, and to polish each one with labels, colours and legends that look professional.
Setting up your Python environment for plotting
The simplest way to start is to install matplotlib using pip from a terminal. Running pip install matplotlib will fetch the library along with the numerical core it depends on, namely NumPy. If you are on a managed machine through your workplace, check with the IT team first, since some Australian organisations lock down pip access behind a corporate proxy.
Once installed, you can import the pyplot interface in any script or Jupyter notebook with the conventional alias. Writing import matplotlib.pyplot as plt keeps the code short and matches the style used in nearly every tutorial, Stack Overflow answer and research notebook you will find online. Pairing this with import numpy as np lets you generate sample data without reaching for a CSV file, which is ideal for quick experiments.
A common first sanity check is to confirm that the backend can render a figure. On a headless server, such as an instance running on AWS Sydney, you may need to set the backend to Agg so plots are written to PNG files rather than displayed interactively. On a personal laptop, the default backend will simply pop up a window the first time you call plt.show().
The core building blocks of pyplot
The pyplot interface works on a current-figure-and-current-axes model, which is worth understanding before writing any code. Each plotting call implicitly refers to whichever figure is active, and a new figure is created the first time you request one. The three functions you will use most often are plt.plot for lines, plt.scatter for points and plt.bar for vertical bars.
Every figure carries an axes object, even when you only draw a single chart, and that object holds the data, the ticks, the labels and the spines. You can either let pyplot create the axes for you, which is fine for quick drafts, or call plt.subplots() to obtain the figure and axes explicitly. The explicit style is preferred when you want fine control over layout, especially when preparing a figure for a report.
Labels, titles and legends attach through dedicated methods on the axes object. Calling ax.set_xlabel, ax.set_ylabel and ax.set_title adds descriptive text, while ax.legend() displays a small key once you have passed a label argument into the plotting function. Keeping these elements in plain English makes the chart easier to read for stakeholders who are not technical.
A useful starter set of plot types to keep in mind includes:
- plt.plot for trends over time or ordered sequences
- plt.scatter for relationships between two continuous variables
- plt.bar for comparing discrete categories
- plt.hist for the distribution of a single numeric column
- plt.pie for parts of a whole, used sparingly
Creating line charts and scatter plots
A line chart is the natural choice when one of your variables advances through time. Suppose you record the maximum temperature in Sydney for every day of January, stored as two NumPy arrays of equal length. Calling plt.plot(days, temperatures) with a label such as "Sydney January" gives you a continuous trace that highlights the warming and cooling swings across the month.
Scatter plots are better when the horizontal axis does not represent a strict order. Plotting the relationship between the price of a flat white in different Melbourne suburbs and the suburb's median rent is a classic example: the points will spread across the plane, and the shape of the cloud tells you whether a correlation exists. Passing the label and a colour keyword into plt.scatter keeps the chart readable.
Both plot types accept styling arguments that you can chain directly into the call. A line style string, a marker character and a colour abbreviation cover the basics, while keyword arguments such as linewidth, alpha and s give you precise control. Setting alpha to a value between 0 and 1 is particularly useful when you have overlapping points, which often happens with high-volume sensor or transaction data.
Building bar charts and histograms
Bar charts summarise categorical comparisons, and pyplot makes them straightforward. A simple comparison of the average monthly rainfall in Brisbane, Perth, Hobart and Darwin can be drawn with a single plt.bar call, where the categories sit on the x-axis and the millimetres on the y-axis. Adding the label parameter and then calling ax.legend() turns the chart into a self-explanatory unit.
Histograms, drawn with plt.hist, are different because they work on a single column of numbers and bin it automatically. They are perfect for showing the distribution of a continuous variable, such as the response times of a public-facing API hosted in an Australian data centre. Adjusting the bins argument lets you change the resolution, which is the most common knob you will turn.
When you have grouped data, a bar chart quickly becomes a clustered or stacked chart by adjusting the position or the bottom argument. For grouped bars, offset each category along the x-axis by a small amount and pass the corresponding width, which keeps the bars side by side. For stacked bars, pass the lower series first and then set the bottom parameter of the upper series to the previous heights.
Customising axes, labels and legends
The default look of a pyplot chart is serviceable, but a few small adjustments turn it into a polished figure. Calling ax.set_xticks and ax.set_xticklabels lets you replace the automatic ticks with custom labels, which is helpful when the data represents months and you want to show short names. Rotating the labels with a rotation argument keeps long categories from overlapping.
Legends should be placed where they do not cover the data, which is often the upper left, upper right or just outside the plot area. Passing loc="best" asks matplotlib to find a quiet spot automatically, while bbox_to_anchor gives you manual control. Keep the wording short and direct, since a legend is a guide rather than a second title.
For readers using assistive technology or printing in greyscale, choosing colour-blind-friendly palettes matters. The viridis and tab10 colormaps, both available through matplotlib, are safer defaults than the legacy jet colormap. Australian accessibility guidance, such as the principles echoed by the Australian Human Rights Commission, encourages designers to consider contrast and colour independence, and charts are no exception.
Saving and exporting your figures
Once a chart looks the way you want, you usually want to save it rather than keep it trapped inside a notebook. Calling plt.savefig with a filename and a target DPI produces a PNG file that you can paste into a slide deck or a Confluence page. For sharper output, a vector format such as SVG or PDF preserves the lines at any zoom level, which is ideal for printed reports.
The savefig function accepts a bbox_inches argument that trims the white margin around the plot, and a transparent flag that lets you drop the background. Both options matter when you embed a chart into a report template that already has its own background colour. If you are working in a Jupyter notebook, the %matplotlib inline magic makes the figure appear directly below the cell, which keeps your workflow tidy.
When the chart will live on a public-facing website, remember that the Australian Competition and Consumer Commission has published guidance on avoiding misleading representations. A chart with a truncated y-axis, for example, can exaggerate small differences and may cross the line into deceptive conduct. Always start bar charts and line charts at zero when the values represent quantities, and label every axis clearly.
Common pitfalls and performance tips
The most frequent beginner mistake is calling plt.show() inside a loop without first calling plt.clf or plt.figure to reset the state. The result is that all of the lines end up on the same axes, often with a rainbow of colours that hides the pattern. Clearing the figure, or better still using a for-loop with plt.subplots, keeps each iteration separate and labelled.
Another trap is forgetting that pyplot keeps a global state across function calls. Defining a function that creates a chart and then calling it twice will often add both charts to the same figure. Wrapping the body of the function in a with plt.style.context(...) block, or simply calling plt.figure() at the top, prevents the leakage.
For very large datasets, the rendering speed of pyplot can become a bottleneck. Reducing the number of points through downsampling, switching to the faster Agg backend, or moving the heavy lifting to dedicated libraries such as datashader can keep the workflow responsive. The same techniques are useful when you are comparing your visualisation skills with peers through algorithmic problem-solving exercises, such as exploring the How to Solve the Longest Increasing Subsequence with Binary Search walkthrough that builds intuition about sequence-based data.
Some issues that catch new users off guard include:
- Mixing plt.plot and ax.plot in the same script and wondering why the legend is empty
- Forgetting plt.tight_layout, which leaves labels clipped at the figure edges
- Using the default colour cycle when the dataset has more than ten categories
- Saving a figure before calling plt.draw, which can produce a blank PNG
- Assuming plt.show blocks execution the same way in a script as in a notebook
Finally, remember that a good chart is often the entry point to a more sophisticated analysis. Once you are comfortable with line, scatter, bar and histogram plots, you can move into heatmaps, contour plots and interactive figures. If your next step is to feed the underlying data into a model, the machine learning section of the hello ML site offers a clear path from plotting to prediction.