orome
orome

Reputation: 48576

What is the idiom for setting the properties in a simple matplotlib figure?

I'm confused by the relationship among matplotlib figures, axes, and subplots.

Usually, I figure out such things by looking at and experimenting with code, which typically embodies the structural relationship among entities in a object model that can be inferred from examples of what works. But in matplotlib I often find a bewildering array of ways to accomplish the same thing, which obscures the underling structure.

For example, if I want to make a simple (no subfigures) log-log figure, any of the following seem to have exactly the same effect.

import matplotlib.pyplot as plt

# All of the following seem to have the same effect:
plt.axes().loglog()
plt.gca().loglog()
plt.loglog()
plt.gcf().gca().loglog()

# These don't work though: 
# plt.gcf().axes().loglog()
# plt.gcf().loglog()

I've tried the documentation and the tutorials, but I'm no wiser having done so.

What does each of the working examples above do? How to they differ? Why do the non-working examples fail? If I'm writing code that I expect others (or me) to be able to read, is one of these idioms preferred over another?


Note that my interest here is in programmatically creating images for publication or export rather than in the interactive creation of figures or in mimicking MATLABs functionality. I gather that some of the "shortcuts" above have to do with making this latter scenario work.

Upvotes: 2

Views: 254

Answers (2)

Olga Botvinnik
Olga Botvinnik

Reputation: 1684

My standard is to get fig, ax from plt.subplots like this:

fig, ax = plt.subplots(1)
ax.loglog(a, b)

I do it this way because then you can also get multiple ax objects as a list, e.g.:

# Make a column of three figures
fig, axes = plt.subplots(3)
for ax, a, b in zip(axes, as, bs):
    ax.loglog(a, b)

Or if you do a 2 by 5 grid, you get a list of lists of ax objects, so I usually unlist the list using axes.flat:

# Make a 2x5 grid of figures
nrows = 2
ncols = 5
height = nrows * 4
width = ncols * 4

# Don't ask me why figsize is (width, height) instead of (height, width)....
fig, axes = plt.subplots(nrows=2, ncols=5, figsize=(width, height))

for ax, a, b in zip(axes.flat, as, bs):
    ax.loglog(a, b)

I do it this way because then I have the ax object to tweak with the appearance with afterwards. I generally don't use plt.gca() except for internal plotting functions.

plt.gcf() is getting the current figure and when you add gca() or axes() or loglog() to it, I believe they create the underlying axes. I'm not sure why the gcf()-first stuff didn't work with axes() and loglog(). So my advice is to stick to ax objects.

EDIT: removed itertools.chain stuff, swapped to axes.flat

Upvotes: 3

Dan
Dan

Reputation: 12705

A figure is basically a window or a file. If you make several separate figures, the idea is usually to pop up several widows or save several files.

An axis and a subplot are in some sense the same thing. For example, the figure method subplot returns an axis object. Each axis object represents a specific set of axes that you want to plot something on. Each axis can have several individual data sets plotted on it, but they will all use the same x and y axes.

Making a plot a loglog plot is determined by the function that you use to actually plot the data. For example, if you have two arrays a and b that I want to loglog plot against each other, I would use:

fig=plt.figure() #Make a figure
loglog_ax=fig.subplot(111) # Make a single axis, which is the *only* subplot
loglog_ax.loglog(a,b) # Plot the data on a log-log plot

Upvotes: 1

Related Questions