Which Is the Recommended Way to Plot: Matplotlib or Pylab

Which is the recommended way to plot: matplotlib or pylab?

From the official documentation, as shown below, the recommendation is to use matplotlib.pyplot. This is not an opinion.

The documentation at Matplotlib, pyplot and pylab: how are they related?, which also describes the difference between pyplot and pylab, states: "Although many examples use pylab, it is no longer recommended.".

2021-05-06 Edit:

  • From The pylab API (disapproved)

Since heavily importing into the global namespace may result in unexpected behavior, the use of pylab is strongly discouraged. Use matplotlib.pyplot instead.

What is the difference between pylab and pyplot?

This wording is no longer in the documentation.

Use of the pylab import is now discouraged and the OO interface is recommended for most non-interactive usage.


From the documentation, the emphasis is mine:

Matplotlib is the whole package; pylab is a module in matplotlib that gets installed alongside matplotlib; and matplotlib.pyplot is a module in matplotlib.

Pyplot provides the state-machine interface to the underlying plotting library in matplotlib. This means that figures and axes are implicitly and automatically created to achieve the desired plot. For example, calling plot from pyplot will automatically create the necessary figure and axes to achieve the desired plot. Setting a title will then automatically set that title to the current axes object:

Pylab combines the pyplot functionality (for plotting) with the numpy functionality (for mathematics and for working with arrays) in a single namespace, making that namespace (or environment) even more MATLAB-like. For example, one can call the sin and cos functions just like you could in MATLAB, as well as having all the features of pyplot.

The pyplot interface is generally preferred for non-interactive plotting (i.e., scripting). The pylab interface is convenient for interactive calculations and plotting, as it minimizes typing. Note that this is what you get if you use the ipython shell with the -pylab option, which imports everything from pylab and makes plotting fully interactive.

matplotlib.pyplot vs matplotlib.pylab

Per the FAQ:

Pyplot provides the state-machine interface to the underlying plotting
library in matplotlib. This means that figures and axes are implicitly
and automatically created to achieve the desired plot....

Pylab combines the pyplot functionality (for plotting) with the numpy
functionality (for mathematics and for working with arrays) in a
single namespace, making that namespace (or environment) even more
MATLAB-like. For example, one can call the sin and cos functions just
like you could in MATLAB, as well as having all the features of
pyplot.

The pyplot interface is generally preferred for non-interactive
plotting (i.e., scripting).
The pylab interface is convenient for
interactive calculations and plotting, as it minimizes typing. (my emphasis.)

Note that

from pylab import *

also performs

from numpy import *

This overwrites many builtin Python functions such as:

In [5]: import __builtin__
In [6]: import numpy as np

In [5]: {name for name in set(dir(np)).intersection(dir(__builtin__)) if not name.startswith('__') and getattr(__builtin__, name) != getattr(np, name)}
Out[5]: {'abs', 'all', 'any', 'max', 'min', 'round', 'sum'}

Therefore, I don't like from pylab import * (or really from module import * for any module) because it makes well-known beloved Python names behave in unexpected ways (if you do not always keep in mind that from numpy import * has polluted the global namespace.)

For example,

In [32]: np.all([np.arange(3), np.arange(3)])
Out[32]: False

while

In [33]: all([np.arange(3), np.arange(3)])
ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()

Confusion between numpy, scipy, matplotlib and pylab

  1. No, pylab is part of matplotlib (in matplotlib.pylab) and tries to give you a MatLab like environment. matplotlib has a number of dependencies, among them numpy which it imports under the common alias np. scipy is not a dependency of matplotlib.

  2. If you run ipython --pylab an automatic import will put all symbols from matplotlib.pylab into global scope. Like you wrote numpy gets imported under the np alias. Symbols from matplotlib are available under the mpl alias.

pylab.X vs pylab.plt.X

If you read the source (the entirety of pylab.py excluding the docstring is below)

from __future__ import print_function
import sys, warnings

from matplotlib.cbook import flatten, is_string_like, exception_to_str, \
silent_list, iterable, dedent

import matplotlib as mpl
# make mpl.finance module available for backwards compatability, in case folks
# using pylab interface depended on not having to import it
import matplotlib.finance

from matplotlib.dates import date2num, num2date,\
datestr2num, strpdate2num, drange,\
epoch2num, num2epoch, mx2num,\
DateFormatter, IndexDateFormatter, DateLocator,\
RRuleLocator, YearLocator, MonthLocator, WeekdayLocator,\
DayLocator, HourLocator, MinuteLocator, SecondLocator,\
rrule, MO, TU, WE, TH, FR, SA, SU, YEARLY, MONTHLY,\
WEEKLY, DAILY, HOURLY, MINUTELY, SECONDLY, relativedelta

import matplotlib.dates # Do we need this at all?

# bring all the symbols in so folks can import them from
# pylab in one fell swoop

## We are still importing too many things from mlab; more cleanup is needed.

from matplotlib.mlab import griddata, stineman_interp, slopes, \
inside_poly, poly_below, poly_between, \
is_closed_polygon, path_length, distances_along_curve, vector_lengths

from matplotlib.mlab import window_hanning, window_none, detrend, demean, \
detrend_mean, detrend_none, detrend_linear, entropy, normpdf, levypdf, \
find, longest_contiguous_ones, longest_ones, prepca, \
prctile, prctile_rank, \
center_matrix, rk4, bivariate_normal, get_xyz_where, \
get_sparse_matrix, dist, \
dist_point_to_segment, segments_intersect, fftsurr, movavg, \
exp_safe, \
amap, rms_flat, l1norm, l2norm, norm_flat, frange, identity, \
base_repr, binary_repr, log2, ispower2, \
rec_append_fields, rec_drop_fields, rec_join, csv2rec, rec2csv, isvector

import matplotlib.mlab as mlab
import matplotlib.cbook as cbook

from numpy import *
from numpy.fft import *
from numpy.random import *
from numpy.linalg import *

from matplotlib.pyplot import *

# provide the recommended module abbrevs in the pylab namespace
import matplotlib.pyplot as plt
import numpy as np
import numpy.ma as ma

# don't let numpy's datetime hide stdlib
import datetime

if sys.version_info > (2, 6, 0):
bytes = __builtins__['bytes']

you see that both every thing from pyplot is imported (from matplotlb.pyplot import * and pyplot) and pyplot is imported (import pyplot as plt). You are not seeing two functions, you are seeing the same function/module imported multiple times.

As to why, why not? pylab is designed for interactive use. It is convenient to have all the function directly in your name space and it is quite handy to have plt in the name space as well for prototyping code.

pylab.X vs pylab.plt.X

If you read the source (the entirety of pylab.py excluding the docstring is below)

from __future__ import print_function
import sys, warnings

from matplotlib.cbook import flatten, is_string_like, exception_to_str, \
silent_list, iterable, dedent

import matplotlib as mpl
# make mpl.finance module available for backwards compatability, in case folks
# using pylab interface depended on not having to import it
import matplotlib.finance

from matplotlib.dates import date2num, num2date,\
datestr2num, strpdate2num, drange,\
epoch2num, num2epoch, mx2num,\
DateFormatter, IndexDateFormatter, DateLocator,\
RRuleLocator, YearLocator, MonthLocator, WeekdayLocator,\
DayLocator, HourLocator, MinuteLocator, SecondLocator,\
rrule, MO, TU, WE, TH, FR, SA, SU, YEARLY, MONTHLY,\
WEEKLY, DAILY, HOURLY, MINUTELY, SECONDLY, relativedelta

import matplotlib.dates # Do we need this at all?

# bring all the symbols in so folks can import them from
# pylab in one fell swoop

## We are still importing too many things from mlab; more cleanup is needed.

from matplotlib.mlab import griddata, stineman_interp, slopes, \
inside_poly, poly_below, poly_between, \
is_closed_polygon, path_length, distances_along_curve, vector_lengths

from matplotlib.mlab import window_hanning, window_none, detrend, demean, \
detrend_mean, detrend_none, detrend_linear, entropy, normpdf, levypdf, \
find, longest_contiguous_ones, longest_ones, prepca, \
prctile, prctile_rank, \
center_matrix, rk4, bivariate_normal, get_xyz_where, \
get_sparse_matrix, dist, \
dist_point_to_segment, segments_intersect, fftsurr, movavg, \
exp_safe, \
amap, rms_flat, l1norm, l2norm, norm_flat, frange, identity, \
base_repr, binary_repr, log2, ispower2, \
rec_append_fields, rec_drop_fields, rec_join, csv2rec, rec2csv, isvector

import matplotlib.mlab as mlab
import matplotlib.cbook as cbook

from numpy import *
from numpy.fft import *
from numpy.random import *
from numpy.linalg import *

from matplotlib.pyplot import *

# provide the recommended module abbrevs in the pylab namespace
import matplotlib.pyplot as plt
import numpy as np
import numpy.ma as ma

# don't let numpy's datetime hide stdlib
import datetime

if sys.version_info > (2, 6, 0):
bytes = __builtins__['bytes']

you see that both every thing from pyplot is imported (from matplotlb.pyplot import * and pyplot) and pyplot is imported (import pyplot as plt). You are not seeing two functions, you are seeing the same function/module imported multiple times.

As to why, why not? pylab is designed for interactive use. It is convenient to have all the function directly in your name space and it is quite handy to have plt in the name space as well for prototyping code.

When to use the matplotlib.pyplot class and when to use the plot object (matplotlib.collections.PathCollection)

According to PEP20:

  • "Explicit is better than implicit."
  • "Simple is better than complex."

Oftentimes, the "make-it-just-work" code takes the pyplot route, as it hides away all of the figure and axes management that many wouldn't care about. This is often used for interactive mode coding, simple one-off scripts, or plotting performed at high-level scripts.

However, if you are creating a library module that is to do plotting, and you have no guarantee that the library user isn't doing any additional plotting of their own, then it is best to be explicit and avoid the pyplot interface. I usually design my functions to accept as optional arguments the axes and/or figure objects the user would like to operate upon (if not given, then I use plt.gcf() and/or plt.gca()).

The rule of thumb I have is that if the operation I am performing could be done via pyplot, but if doing so would likely change the "state machine", then I avoid pyplot. Note that any action via pyplot (such as plt.xlim()) gets/sets the current axes/figure/image (the "state machine"), while actions like ax.set_xlim() do not.

UserWarning: Matplotlib is currently using agg, which is a non-GUI backend, so cannot show the figure. when plotting figure with pyplot on Pycharm

Solution 1: is to install the GUI backend tk

I found a solution to my problem (thanks to the help of ImportanceOfBeingErnest).

All I had to do was to install tkinter through the Linux bash terminal using the following command:

sudo apt-get install python3-tk

instead of installing it with pip or directly in the virtual environment in Pycharm.

Solution 2: install any of the matplotlib supported GUI backends

  • solution 1 works fine because you get a GUI backend... in this case the TkAgg
  • however you can also fix the issue by installing any of the matplolib GUI backends like Qt5Agg, GTKAgg, Qt4Agg, etc
    • for example pip install pyqt5 will fix the issue also

NOTE:

  • usually this error appears when you pip install matplotlib and you are trying to display a plot in a GUI window and you do not have a python module for GUI display.
  • The authors of matplotlib made the pypi software deps not depend on any GUI backend because some people need matplotlib without any GUI backend.


Related Topics



Leave a reply



Submit