A picture is worth a thousand words, and with Python’s **matplotlib** library, it fortunately takes far less than a thousand words of code to create a production-quality graphic.

However, matplotlib is also a massive library, and getting a plot to look just right is often achieved through trial and error. Using one-liners to generate basic plots in matplotlib is fairly simple, but skillfully commanding the remaining 98% of the library can be daunting.

This article is a beginner-to-intermediate-level walkthrough on matplotlib that mixes theory with examples. While learning by example can be tremendously insightful, it helps to have even just a surface-level understanding of the library’s inner workings and layout as well.

Here’s what we’ll cover:

- Pylab and pyplot: which is which?
- Key concepts of matplotlib’s design
- Understanding
`plt.subplots()`

- Visualizing arrays with matplotlib
- Plotting with the pandas + matplotlib combination

**Free Bonus:** Click here to download 5 Python + Matplotlib examples with full source code that you can use as a basis for making your own plots and graphics.

This article assumes the user knows a tiny bit of NumPy. We’ll mainly use the `numpy.random`

module to generate “toy” data, drawing samples from different statistical distributions.

If you don’t already have matplotlib installed, see here for a walkthrough before proceeding.

## Why Can Matplotlib Be Confusing?

Learning matplotlib can be a frustrating process at times. The problem is not that matplotlib’s documentation is lacking: the documentation is actually extensive. But the following issues can cause some challenges:

- The library itself is huge, at something like 70,000 total lines of code.
- Matplotlib is home to several different interfaces (ways of constructing a figure) and capable of interacting with a handful of different backends. (Backends deal with the process of how charts are actually rendered, not just structured internally.)
- While it is comprehensive, some of matplotlib’s own public documentation is seriously out-of-date. The library is still evolving, and many older examples floating around online may take 70% fewer lines of code in their modern version.

So, before we get to any glitzy examples, it’s useful to grasp the core concepts of matplotlib’s design.

## Pylab: What Is It, and Should I Use It?

Let’s start with a bit of history: John D. Hunter, a neurobiologist, began developing matplotlib around 2003, originally inspired to emulate commands from Mathworks’ MATLAB software. John passed away tragically young at age 44, in 2012, and matplotlib is now a full-fledged community effort, developed and maintained by a host of others. (John gave a talk about the evolution of matplotlib at the 2012 SciPy conference, which is worth a watch.)

One relevant feature of MATLAB is its global style. The Python concept of importing is not heavily used in MATLAB, and most of MATLAB’s functions are readily available to the user at the top level.

Knowing that matplotlib has its roots in MATLAB helps to explain why pylab exists. pylab is a module within the matplotlib library that was built to mimic MATLAB’s global style. It exists only to bring a number of functions and classes from both NumPy and matplotlib into the namespace, making for an easy transition for former MATLAB users who were not used to needing `import`

statements.

Ex-MATLAB converts (who are all fine people, I promise!) liked this functionality, because with `from pylab import *`

, they could simply call `plot()`

or `array()`

directly, as they would in MATLAB.

The issue here may be apparent to some Python users: using `from pylab import *`

in a session or script is generally bad practice. Matplotlib now directly advises against this in its own tutorials:

“[pylab] still exists for historical reasons, but it is highly advised not to use. It pollutes namespaces with functions that will shadow Python built-ins and can lead to hard-to-track bugs. To get IPython integration without imports the use of the

`%matplotlib`

magic is preferred.” [Source]

Internally, there are a ton of potentially conflicting imports being masked within the short pylab source. In fact, using `ipython --pylab`

(from the terminal/command line) or `%pylab`

(from IPython/Jupyter tools) simply calls `from pylab import *`

under the hood.

The bottom line is that **matplotlib has abandoned this convenience module and now explicitly recommends against using pylab,** bringing things more in line with one of Python’s key notions: explicit is better than implicit.

Without the need for pylab, we can usually get away with just one canonical import: