-
-
Notifications
You must be signed in to change notification settings - Fork 8.2k
Description
Summary
Matplotlib is often considered verbose. I've been pondering whether/how one could write the code more compact without completely reinventing our API. The two main points for simplification I've come up with are:
- Don't use
set_*for configuration, but instead do the configuration via kwargs. Theset_*methods can be a fallback for mor complex configuration. - Don't hold a figure reference as it's rarely needed.
What I explicitly do not want to change:
- No breakage of existing API
- No completely new interface namespace
- No method chaining
This is just an early and wild idea, not a proposal. Thoughts and feedback are welcome.
Proposed fix
The ideas are illustrated on a slightly modified variant of https://matplotlib.org/devdocs/gallery/lines_bars_and_markers/simple_plot.html
The formal Axes interface approach is:
fig, ax = plt.subplots()
ax.plot(t, s)
ax.set_xlabel('time (s)')
ax.set_ylabel('voltage (mV)')
ax.set_title('A simple plot')
plt.show()In some parts, we already have replaced the individual setters by ax.set(...) with kwargs.
fig, ax = plt.subplots()
ax.plot(t, s)
ax.set(xlabel='time (s)', ylabel='voltage (mV)', title='A simple plot')
plt.show()Possible improvement 1: Replace ax.set(...) by kwargs during Axes creation:
fig, ax = plt.subplots(xlabel='time (s)', ylabel='voltage (mV)', title='A simple plot')
ax.plot(t, s)
plt.show()Possible improvement 2: Don't store a reference to the figure - rationale: The fig, ax = plt.subplots() pattern is quite boilerplate and you rarely need the figure. One can always get the figure via ax.get_figure() if needed, which is only mildy more work than holding a fig variable.
ax = plt.figure().subplots(xlabel='time (s)', ylabel='voltage (mV)', title='A simple plot')
ax.plot(t, s)
plt.show()What is still not so nice is that you still need the plt.figure().subplots( chaining for the simple single-Axes case. While
ax = plt.axes(xlabel='time (s)', ylabel='voltage (mV)', title='A simple plot')works with the same result, there's a caveat in that plt.axes() reuses an existing Figure if possible whereas plt.figure().subplot() always creates a new figure. That's a potential footgun and we may want to think whether there's a way around this. Otherwise
ax = plt.axes(xlabel='time (s)', ylabel='voltage (mV)', title='A simple plot')
ax.plot(t, s)
plt.show()would look quite clean to me:
- create an Axes with some properties set
- add data
- show
In jupyter notebooks you'd even not need the show and could (as an abbreviation, not as a universally recommended pattern) create the plot in one line:
plt.axes(xlabel='time (s)', ylabel='voltage (mV)', title='A simple plot').plot(t, s)