below is my code that plots a function, and I need to move the “X” and “Y” labels into the first quadrant, to where they are conventionally placed near the corresponding arrows. how is this done?
import pylab as p
import numpy as n
from mpl_toolkits.axes_grid import axislines
def cubic(x) :
return x**3 + 6*x
def set_axes():
fig = p.figure(1)
ax = axislines.SubplotZero(fig, 111)
fig.add_subplot(ax)
for direction in ['xzero', 'yzero']:
ax.axis[direction].set_axisline_style('->', size=2)
ax.axis[direction].set_visible(True)
for direction in ['right', 'top', 'left', 'bottom']:
ax.axis[direction].set_visible(False)
ax.axis['xzero'].set_label('X')
ax.axis['yzero'].set_label('Y')
ax.axis['yzero'].major_ticklabels.set_axis_direction('right')
ax.axis['yzero'].set_axislabel_direction('+')
ax.axis['yzero'].label.set_rotation(-90)
ax.axis['yzero'].label.set_va('center')
set_axes()
X = n.linspace(-15,15,100)
Y = cubic(X)
p.plot(X, Y)
p.xlim(-5.0, 5.0)
p.ylim(-15.0, 15.0)
p.xticks(n.linspace(-5, 5, 11, endpoint=True))
p.grid(True)
p.show()
Normally, to change an axis’s (e.g.
ax.xaxis) label position, you’d doaxis.label.set_position(xy). Or you can just set one coordinate, e.g. ‘ax.xaxis.set_x(1)`.In your case, it would be:
However,
axislines(and anything else inaxisartistoraxes_grid) is a somewhat outdated module (which is whyaxes_grid1exists). It doesn’t subclass things properly in some cases. So, when we try to set the x and y positions of the labels, nothing changes!A quick workaround would be to use
ax.annotateto place labels at the ends of your arrows. However, let’s try making the plot a different way first (after which we’ll wind up coming back toannotateanyway).These days, you’re better off using the new spines functionality to do what you’re trying to accomplish.
Setting the x and y axes to be “zeroed” is as simple as:
However, we still need the nice arrow decoration. This is a bit more complex, but it’s just two calls to annotate with the approriate arguments.
(The width of the arrow is controlled by the text size (or an optional parameter to the
arrowprops), so specifying something likesize=16toannotatewill make the arrow a bit wider, if you’d like.)At this point, it’s easiest to just add the “X” and “Y” labels as a part of the annotation, though setting their positions would work as well.
If we just pass in a label as the first argument to annotate instead of an empty string (and change the alignment a bit) we’ll get nice labels at the ends of the arrows:
With a only a tiny bit more work (directly accessing the spine’s transform), you can generalize the use of annotate to work with any type of spine alignment (e.g. “dropped” spines, etc).
At any rate, hope that helps a bit. You can also get fancier with it, if you’d like.