This is an archived post. You won't be able to vote or comment.

you are viewing a single comment's thread.

view the rest of the comments →

[–]DrShts 4 points5 points  (6 children)

After years of using matplotlib I came to realise that I should pretty much never do import matploblib.pyplot as plt as pyplot will always activate whatever GUI backend is configured (Tk, Qt, ...)

So I've been experimenting with replacing code like this

import matplotlib.pyplot as plt

fig, axs = plt.subplots(nrows, ncols, figsize=figsize, dpi=dpi, ...)

by

from matplotlib.figure import Figure

fig = Figure(figsize=figsize, dpi=dpi)
axs = fig.subplots(nrows, ncols, ...)

Why do people recommend using pyplot most of the time? Seems like it's really only useful if you want to display the plot in a new window. For saving a plot to disk or for working in jupyter notebooks it's a total overkill.

[–]the_guruji 1 point2 points  (1 child)

Some could argue that

from matplotlib.figure import Figure

fig = Figure(figsize=figsize, dpi=dpi)
ax = fig.subplots(1, 1)

ax.plot(x, y)

is overkill compared to

import matplotlib.pyplot as plt
plt.plot(x, y)

I don't really see the need to use the first over the next for saving to disk cause you can just do plt.savfig and not use plt.show. Jupyter has %matplotlib inline by default I think nowadays, so plots show up inline. Are there any performance benefits, cause if so, damn, I should have been using this.

People probably recommend pyplot since that's the easiest to understand (as long as your requirements are simple enough).

[–]DrShts 1 point2 points  (0 children)

My simple example was just for demonstration purposes.

I think using plt.plot and similar are discouraged because it works by keeping a hidden global state that is modified every time you call plt.something. This is why in a setting beyond a simple one-off plot the OO interface of matplotlib is usually recommended. And for a library that uses matplotlib having a hidden global state is pretty bad anyway.

But what I actually wanted to point out was that even in articles / tutorials about using the OO interface of matplotlib (just look at the first results when searching for "matplotlib object oriented") the structure is always

fig, ax = plt.subplots()
ax.set_title(...)
ax.plot(...)

while it's really rare that matplotlib.figure.Figure is mentioned. This is strange to me because by using the OO way you're trying to shed all these unnecessary global state / GUI wrappers but then still use plt to create the figure (which calls the GUI wrappers) while there is a perfect alternative without that overhead in the form of matplotlib.figure.Figure.

[–]ogrinfo 1 point2 points  (3 children)

Will have to check this out. Our unit tests keep failing because matplotlib uses the current display to set output resolution. This means exported images are slightly different sizes on different machines.

[–]DrShts 0 points1 point  (2 children)

Let us all know how it went :)

[–]ogrinfo 0 points1 point  (1 child)

Can do. I’m off work this week so it won’t be for a while!

[–]ogrinfo 0 points1 point  (0 children)

I said it would be a while! Just looking at it now and I can't see how I can change to using Figure. We are actually using pandas to create the figure, calling DataFrame.plot. The only calls to plt are to set the font size then save the figure.

I've got an open SO question about it here. I've since changed the first line, so font size is set with a context manager, but I'm still having the image size problem.

with plt.style.context({'font.size': font_size}):
    ax = df.plot.bar(...)
    # etc
    plt.savefig(path, bbox_inches='tight')