Add tick labels on right yaxis in matplotlib - python

I have the following graph:
I'd like to add custom ticks with labels on the right hand side of the graph, to identify the dashed horizontal lines. How can I do that?

ax = gca()
ax.axhline(.5, linestyle='--')
trans = matplotlib.transforms.blended_transform_factory(
ax.transAxes,
ax.transData)
ax.annotate('label', xy=(1.01, .5), xycoords=trans, clip_on=False, va='center')
ax.set_xlim([0,2])
plt.draw()
See here for details on blended transforms. The x coordinate in is axis units (so it will always be just a tad off to the right, and the y-coordinate is is data units so you can put it exactly where you want. There isn't much point in putting in ticks on the right because you dashed lines will cover them up.

If you want a new scale, use twinx().
fig = plt.figure()
ax = []
ax.append(fig.add_subplot(111))
ax.append(ax[0].twinx())
ax[0].plot(...)
ax[1].set_yticks([...])
ax[1].set_yticklabels([...])
plt.show()
If you want just a label, use a text thingy, as #tcaswell wrote.

Related

Is it possible to draw xticklabels on top of the xaxis?

I want to mark a specific x-axis position with a colored asterisk drawn on top of the x-axis.
I use an x-tick label as the marker (because I couldn't figure out if it is possible to place markers anywhere in the fig coords) at it's aligned properly but is drawn below the x-axis so it's partially covered.
MWE:
import numpy as np
import matplotlib.pyplot as plt
fig,ax=plt.subplots(1,1)
ax.scatter([-1,1],[1,1])
ax.set_xticks([0],minor=True)
ax.set_xticklabels(['*'],minor=True,color='r',fontsize=20,verticalalignment='center')
plt.setp(ax.spines.values(), linewidth=3)
plt.show()
That's what it looks like right now:
You can specify the coordinates of a scatter in a blended system (data coordinates for the y axis and axis coordinates for the x axis).
To then have the scatter marker above the spines set the zorder property of the scatter to something above 2.5.
import matplotlib.pyplot as plt
fig,ax=plt.subplots(1,1)
ax.scatter([-1,1],[1,1])
ax.scatter(0,0, s=100, marker="*", color="red",
transform=ax.get_xaxis_transform(), clip_on=False, zorder=3)
plt.show()
What you are looking for is zorder parameter. By using zorder = 0, you basically define the order of stacking of the plot sequence. 0 would send the axis/frame in the background putting the asterisk over the axis line as desired. I increased the size of the asterisk to highlight it.
ax.scatter([-1,1],[1,1])
ax.set_xticks([0],minor=True)
ax.set_xticklabels(['*'],minor=True,color='r',fontsize=30,verticalalignment='center')
plt.setp(ax.spines.values(), linewidth=3, zorder=0)
Alternatively, you can also specify the zorder for both plotting commands but use a higher zorder for the asterisk
ax.set_xticklabels(['*'],minor=True,color='r',fontsize=30,verticalalignment='center', zorder=2)
plt.setp(ax.spines.values(), linewidth=3, zorder=1)

Bring radial axes labels in front of lines of polar plot matplotlib

I am trying to get the radial (or y-axis) labels on a polar plot to go on top of the lines that are plotted on the graph. Right now they are underneath the lines and are covered up.
Here is a simplified version of the code for just one city and one line:
fig, ax = plt.subplots(figsize=(10,6) , nrows=1, ncols=1,subplot_kw=dict(projection='polar'))
rmax = 15
rticks = np.arange(9,rmax,1.5)
rticklabel = np.arange(18,rmax*2,3).astype(int)
theta = np.arange(0,6.3, 0.17) #plots a circle
r = np.ones(len(theta))*(21/2)
ax.plot(theta, r,c='r', linestyle='-',linewidth = 4,zorder=1)
ax.set_rmax(rmax)
ax.set_rticks(rticks) # less radial ticks
ax.set_xticklabels([])
ax.set_rlabel_position(285) # get radial labels away from plotted line
ax.grid(True)
ax.set_facecolor('white')
ax.yaxis.grid(color='silver', linestyle=':',linewidth = 1.5,zorder=10)
ax.set_yticklabels(rticklabel,fontsize=12,zorder=10) #this zorder does nothing
I have already tried this:
plt.rcParams["axes.axisbelow"] = False
This brings the text to the front as I wish, however, it also brings the grid lines. I would like those to stay behind the colored lines.
I have also tried changing the zorder of the yaxis grid, but that does not work.
Most solutions for this are not for the polar axis. Any suggestions?
Unfortunately it seems that the zorder of the grid and labes is tied to that of the axes: https://matplotlib.org/api/_as_gen/matplotlib.axes.Axes.grid.html
One possible solution even if not elegant is to draw the gridlines yourself
fig, ax = plt.subplots(figsize=(10,6) , nrows=1, ncols=1,subplot_kw=dict(projection='polar'))
rmax = 15
rticks = np.arange(9,rmax,1.5)
rticklabel = np.arange(18,rmax*2,3).astype(int)
theta = np.arange(0,6.3, 0.17) #plots a circle
r = np.ones(len(theta))*(21/2)
ax.plot(theta, r,c='r', linestyle='-',linewidth = 4,zorder=2)
ax.set_rticks(rticks) # less radial ticks
ax.set_xticklabels([])
ax.set_rlabel_position(285) # get radial labels away from plotted line
ax.xaxis.grid(True)
ax.yaxis.grid(False)
ax.set_facecolor('white')
ax.set_yticklabels(rticklabel,fontsize=12,zorder=10) #this zorder does nothing
ax.yaxis.set_zorder(10)
#ax.yaxis.grid(color='silver', linestyle=':',linewidth = 1.5,zorder=10)
x = np.arange(0,2*np.pi,0.05)
y = np.outer( np.ones(x.shape), rticks)
ax.plot( x,y, zorder=1, color='silver', linestyle=':')
ax.set_ylim(0,rmax)

matplotlib plot to fill figure only with data points, no borders, labels, axes,

I am after an extreme form of matplotlib's tight layout.
I would like the data points to fill the figure from edge to edge without
leaving any borders and without titles, axes, ticks, labels or any other decorations.
I want to do something like what figimage does, but for plots instead of raw images.
How do I do that in matplotlib?
While a solution may be found taking the bits and pieces from an answer to this question it may not be obvious at first sight.
The main idea to have no padding around the axes, is to make the axes the same size as the figure.
fig = plt.figure()
ax = fig.add_axes([0,0,1,1])
Alternatively, one can set the outer spacings to 0.
fig, ax = plt.subplots()
plt.subplots_adjust(left=0, right=1, bottom=0, top=1)
Then, in order to remove the axis decorations one can use
ax.set_axis_off()
or
ax.axis("off")
This may now still leave some space between the plotted line and the edge. This can be removed by setting the limits appropriately using ax.set_xlim() and ax.set_ylim(). Or, by using ax.margins(0)
A complete example may thus look like
import matplotlib.pyplot as plt
fig = plt.figure()
ax = fig.add_axes([0,0,1,1])
ax.axis("off")
ax.plot([2,3,1])
ax.margins(0)
plt.show()

matplotlib: Aligning twin y-axes

The answer to this question suggests that I play around with the set_ylim/get_ylim in order to align two twin axes. However, this does not seem to be working out for me.
Code snippet:
fig, ax1 = plt.subplots()
yLim = [minY, maxY]
xLim = [0, 0.01]
for x in analysisNumbers:
ax1.plot(getData(x), vCoords, **getStyle(x))
ax1.set_yticks(vCoords)
ax1.grid(True, which='major')
ax2 = ax1.twinx()
ax2.set_yticks(ax1.get_yticks())
ax2.set_ylim(ax1.get_ylim())
ax2.set_ylim(ax1.get_ylim())
plt.xlim(xLim[0], xLim[1])
plt.ylim(yLim[0], yLim[1])
plt.minorticks_on()
plt.show()
Graph output (open image in a new window):
The twin axes should be the same, but they are not. Their labels are the same, but their alignment is not (see that the zeroes do not line up). What's wrong?
As tcaswell points out in a comment, plt.ylim() only affects one of the axes. If you replace these lines:
ax2.set_ylim(ax1.get_ylim())
ax2.set_ylim(ax1.get_ylim())
plt.xlim(xLim[0], xLim[1])
plt.ylim(yLim[0], yLim[1])
with this:
ax1.set_ylim(yLim[0], yLim[1])
ax2.set_ylim(ax1.get_ylim())
plt.xlim(xLim[0], xLim[1])
It'll work as I'm guessing you intended.

In matplotlib, how do you display an axis on both sides of the figure?

I want to draw a plot with matplotlib with axis on both sides of the plot, similar to this plot (the color is irrelevant to this question):
How can I do this with matplotlib?
Note: contrary to what is shown in the example graph, I want the two axis to be exactly the same, and want to show only one graph. Adding the two axis is only to make reading the graph easier.
You can use tick_params() (this I did in Jupyter notebook):
import matplotlib.pyplot as plt
bar(range(10), range(10))
tick_params(labeltop=True, labelright=True)
Generates this image:
UPD: added a simple example for subplots. You should use tick_params() with axis object.
This code sets to display only top labels for the top subplot and bottom labels for the bottom subplot (with corresponding ticks):
import matplotlib.pyplot as plt
f, axarr = plt.subplots(2)
axarr[0].bar(range(10), range(10))
axarr[0].tick_params(labelbottom=False, labeltop=True, labelleft=False, labelright=False,
bottom=False, top=True, left=False, right=False)
axarr[1].bar(range(10), range(10, 0, -1))
axarr[1].tick_params(labelbottom=True, labeltop=False, labelleft=False, labelright=False,
bottom=True, top=False, left=False, right=False)
Looks like this:
There are a couple of relevant examples in the online documentation:
Two Scales (seems to do exactly what you're asking for)
Dual Fahrenheit and Celsius
I've done this previously using the following:
# Create figure and initial axis
fig, ax0 = plt.subplots()
# Create a duplicate of the original xaxis, giving you an additional axis object
ax1 = ax.twinx()
# Set the limits of the new axis from the original axis limits
ax1.set_ylim(ax0.get_ylim())
This will exactly duplicate the original y-axis.
Eg:
ax = plt.gca()
plt.bar(range(3), range(1, 4))
plt.axhline(1.75, color="gray", ls=":")
twin_ax = ax.twinx()
twin_ax.set_yticks([1.75])
twin_ax.set_ylim(ax.get_ylim())

Categories