matplotlib one centered axis label for two diagrams - matplotlib

I'd like to have one axis label centered over two axes in matplotlib.
For example, I set up the axes as follows:
figure = pyplot.figure(figsize=10,10))
diagram1 = figure.add_axes([0.01,0.62,0.90,0.30])
diagram2 = figure.add_axes([0.01,0.32,0.90,0.30])
This will generate two diagrams on top of each other. How can i now define one axis label for the y axis centered on both diagrams.
I think this can be done with subplots, but I prefer to set every diagram individually, as shown above.

You can manually change the y-coordinate of the label.
diagram1.set_ylabel('y label').set_y(0)
# Alternatively you can use
# diagram2.set_ylabel('y label').set_y(1)
The coordinate is in the axes coordinate space, meaning 0 is the bottom and 1 is the top of the Axes.
Seeing how your Axes are placed at x=0.01, you can make the label appear at the right side of the plots as well
diagram1.yaxis.set_label_position("right")

Related

overlapping constrained 3d subplots

What knobs must I tweak to prevent these problems:
overlapping axes labels
overlapping plots with cropped axes labels
I'm using matplotlib 3.5.1 with the PGF backend. Some solutions for older versions no longer work.
fig, axes = plt.subplots\
(2, 3, constrained_layout=True, subplot_kw=dict(projection="3d"))
#it = np.nditer(axes, flags=["refs_ok","multi_index"])
#for ax in it:
# # Plot the surfaces, add row and column title annotations.
# pass
width = 150 * 0.8 * mm
height = width * 0.65
fig.set_size_inches(width, height)
fig.savefig("something.pgf", dpi=300)
plt.close(fig)
Getting rid of the constrained layout and using plt.subplots_adjust(wspace=<value>, hspace=<value>) worked for me
from matplotlib import pyplot as plt
fig, axes = plt.subplots(nrows=2, ncols=3, subplot_kw=dict(projection="3d"))
plt.subplots_adjust(wspace=0.5,hspace=0.5)
labels_x, labels_y, labels_z = [['x-axis']*3]*2, [['y-axis']*3]*2, [['z-axis']*3]*2
for i in range(len(axes)):
for j in range(len(axes[i])):
axes[i,j].set_xlabel(labels_x[i][j])
axes[i,j].set_ylabel(labels_y[i][j])
axes[i,j].set_zlabel(labels_z[i][j])
plt.show()
While both tight and constrained layouts can be used with 3d projection (mplot3d) it seems that constrained layout does not understand how to pad 3d tick labels, leading to overlapping or trimmed labels. Both layout managers adjust subplot padding and axes size given a fixed figure size. Neither can fit the figure size to the contents. To do so with tight layout, extrapolate the desired figure size from the current figure tight bbox over multiple iterations. When using the constrained layout manager, sum the axes tight bboxes and padding to determine any extraneous space. Tight layout adjusts subplotpars (axes size and figure padding) and supports "h_pad" and "w_pad" parameters. Constrained layout adjusts axes size and supports "wspace", "hspace", "w_pad", and "h_pad" parameters. The tight layout squeezes subplots into a tight group which is then centered in the available space. The constrained layout distributes subplots evenly across all available space. Regardless of the layout manager, if the ticks overlap or are clustered too tightly, switch the tick locator to "MaxNLocator" for some smaller "n".
The root problem is that the 3d projection tick labels are empty until a full canvas draw. The "_draw_disabled" draw performed by the constrained layout manager isn't sufficient to trigger the tick labels. If you trace the axes tight bbox you'll notice they don't include the labels until after a call to "fig.canvas.draw", before then the tick labels are just "Text(0, 0, '')". Be sure to include this call after sizing the figure and then the layout will be constrained as expected. Given a fixed figure width, set the height based on aesthetics or sum the axes tight bboxes with padding to determine the minimum possible height.

subplot with shared axis but different ticks and labels

I make a plot with different subplots (using gridspec.GridSpec). Two subplots share the same x-axis (sharex=ax1 in the definition of the second subplot).
However, as one subplot shows the indices of the chronologically sorted data, and the second subplot shows the corresponding decades, I want seperate ticks and labels for the x-axes of both plots. This seems not possible, a unique set of labels and ticks are assigned to both subplots. Until now, I can only:
use different x-axes and thus assign two sets of ticks and labels.
In that case, the axes are not alligned although
ax1.set_xlim([start, stop]) are similarly defined for both subplots
use a common x-axis and one set of ticks and labels
I do not find a solution for this on the internet. Is someone able to help? Thank you in advance!

Matplotlib: How to place x-axis and y-axis TITLES at edges of frame, even if origin is not at bottom left?

I'm making plots where the (0,0) position is not necessarily in the bottom left corner of the plot frame, meaning that the x and y axes and their ticks cross within the plot frame. It's fine to have the lines, ticks and their values within the frame, but having the axis titles so near to their lines interferes with visualization of certain data points.
I'd simply like to force the x and y axis titles to be at the bottom and far left of the plot frame, respectively; it doesn't work to simply 'pad' the xlabel or ylabel titles because the padding I'd need would vary between plots.
How to get the titles always in these consistent locations of the plot frame, even if the corresponding axis lines, ticks/values may vary in the plot frame space?
Thank you.
I'd like to add a note here. It seemed to me that it could be possible to define the xlabel and ylabel 'labelpad' values directly from the data range:
For example, one could find the minimum x-value of the minimum y-value (this would set the position of the x-axis label), and the minimum x-value of the minimum x-value (this would set the position of the y-axis label):
xpad = ax.get_ylim()[0]
ypad = ax.get_xlim()[0]
Then use these values in xlabel and ylabel parameters as labelpads:
pylab.xlabel("X Title", fontsize=12, labelpad=abs(xpad))
pylab.ylabel("Y Title", fontsize=12, labelpad=abs(ypad))
Unfortunately, it doesn't look like labelpad can accept variables. Any suggestions that might allow a work-around?

Matplotlib's Figure and Axes explanation

I am really pretty new to matplotlib, though I know that it can be very powerful.
I've been reading number of tutorials and examples and it's a real hassle to understand how does matplotlib's Figure and Axes work. I am illustrating, what I am trying to understand, with the attached figure.
I know how to create a figure instance of certain size in inches. However, what bothers me is how can I create subplots and then axes, within each subplot, with relative coordinates (bottom=0,left=0,top=1,right=1) as illustrated.
So, for example I want to create a "parent" plot area (say (6in,10in)). Then, I want to create two subplot areas, each with size (3in,3in), with 1in space from the top, 2in space between the two vertical subplot areas and 1in from bottom. Then, 1in space on the left and 2in space on the write. In the same time, I would like to be able to get the coordinates of the subplot areas with respect to the main plot area.
Then, inside the first subplot area, I'd like to create 2 axis instances, with Axis 1, having coordinates with respect to Subplot Area1 (0.1,0.7,0.7,0.2) and Axes 2 (0.1,0.2,0.7,0.5). And then of course I'd like to be able to plot on these axes e.g., ax1.plot()....
If you could provide a sample code to achieve that, then I can study it.
Your help will be very much appreciated!
a subplot and an Axes object are really the same thing. There is not really a "subplot" as you describe it in matplotlib. You can just create your three Axes objects using gridspec without the need to put them in your "subplots".
There are a few different ways to create Axes instances within your figure.
fig.add_axes will create an Axes instance at the position given to it (you give it [left,bottom,width,height] in figure coordinates (i.e. 0,0 is bottom left, 1,1 is top right).
fig.add_subplot will also create an Axes instance. In this case, rather than giving it a rectangle to be created in, you give it the number of rows and columns of subplots you would like, and then the plot_number, where plot_number starts at 1, increments across rows first and has a maximum of nrows * ncols.
For example, to create the top-left Axes in a grid of 2 row and 2 columns, you could do the following:
fig.add_subplot(2,2,1)
or the shorthand
fig.add_subplot(221)
There are some more customisable ways to create Axes as well, for example gridspec and subplot2grid which allow for easy creation of many subplots of different shapes and sizes.

Use free space after hiding axis

I have a horizontal bar chart where I decided to hide the Y axis and display the axis labels inside the chart:
Now I'd like to know how I can tell Dimple to use the free space (see red rectangle) available from hiding the Y axis.
You set the bounds of the plot area with setMargins or setBounds. Dimple doesn't automatically size to accommodate axes. So just set the left margin to about 10px.