4

Having read this Q&A I know how I can specify optional arguments to a y label object, using either the pyplot namespace

plt.ylabel('y', rotation='horizontal', ha='right')

or the object oriented one

ax.set_ylabel(...)

but I don't know how I could possibly use the convenient syntax

ax.set(ylabel=???)

and still be able to specify additional parameters.

gboffi
  • 22,939
  • 8
  • 54
  • 85
  • What exactly do you mean by "*still be able to specify additional parameters*"? `ax.set()` accepts multiple parameters, as I surmise you know – William Miller Jun 13 '20 at 11:48
  • 1
    @WilliamMiller I'd like to say e.g. `ax.set(ylabel=dict(text='y', ha='right', fonstsize=13))` but that does not work, so I'm here, asking if there is a way of tricking `ax.set` to do what I want... – gboffi Jun 13 '20 at 13:23
  • You may want to consider including that piece of code in the question body - it is very helpful in clarifying exactly what it is you're looking for. – William Miller Jun 15 '20 at 03:08

2 Answers2

2

A simple example of its usage:

import matplotlib
import matplotlib.pyplot as plt
import numpy as np

# Data for plotting
t = np.arange(0.0, 2.0, 0.01)
s = 1 + np.sin(2 * np.pi * t)

fig, ax = plt.subplots()
ax.plot(t, s)

ax.set(xlabel='time (s)', ylabel='voltage (mV)',
       title='About as simple as it gets, folks')
ax.grid()

fig.savefig("test.png")
plt.show()

Beware that the options available to the other two approach you mention will not be available when using ax.set(), because this is only "a property batch setter", hence only properties of Axes will be exposed.

Idea O.
  • 420
  • 4
  • 10
  • I'm afraid that your answer doesn't contribute, unless you can give a sound reference/explanation of your last last statement. I'm sorry that my question led you to understand that I don't know how to use `ax.set()` but now I have edited it. – gboffi Jun 13 '20 at 08:56
  • @gboffi I think that the last sentence in the answer addresses precisely the last sentence in the question: you cannot use e.g. `rotation` etc in `set`. Only `Axes` properties are available through `set()`. – Idea O. Jun 13 '20 at 09:04
  • _"… unless you can give a sound reference/explanation of your last last statement."_ – gboffi Jun 13 '20 at 10:46
  • 1
    @gboffi how about the official documentation? – Idea O. Jun 13 '20 at 10:56
  • Give an extract of the official documentation then – gboffi Jun 15 '20 at 09:54
  • @gboffi That is what I did: "a property batch setter" is the relevant extract of the docs – Idea O. Jun 15 '20 at 10:21
1

The Axes class doesn't have an override for the set() method, so matplotlib.axes.Axes.set() is the same as matplotlib.artist.Artist.set() which calls matplotlib.artist.Artist.update() with the the specified keyword argument list (props). update() looks like this:

def update(self, props):
    ret = []
    with cbook._setattr_cm(self, eventson=False):
        for k, v in props.items():
            # ...
            if k == "axes":
                ret.append(setattr(self, k, v))
            else:
                func = getattr(self, f"set_{k}", None)
                if not callable(func):
                    raise AttributeError(f"{type(self).__name__!r} object "
                                         f"has no property {k!r}")
                ret.append(func(v))
    # ....
    return ret

This goes through the props dict and checks if a setter method of self (in the case of matplotlib.axes.Axes.set() the Axes instance) exists for each key, if it does then it calls it with the associated value, if not it raises an AttributeError. This means that you can't use the set() method to change attributes for which there is no defined setter method (the one exception is that you can pass the axes argument to reset the axes).

Since matplotlib.axes.Axes does not have a setter for the label rotations and alignments, you can't use ax.set() to mutate these. What you can do is call .set() on the text instance instead, i.e.

import matplotlib.pyplot as plt

fig, ax = plt.subplots(1)
ylab = ax.set_ylabel("y-label")
ylab.set(rotation="horizontal", ha="right")

I think this is the closest to your desired usage that is possible with .set().

William Miller
  • 9,839
  • 3
  • 25
  • 46