Set space between axis label and axis - python

Is there a way of specifying the position of axis labels?
labelpad sets the space between tick labels and the axis label.
Since the width of tick labels is unknown it appears to thus be impossible to precisely position axis labels.
Here is a MWE where I would like to have the ylabels of both subplots to be vertically aligned:
import numpy as np
import matplotlib
import matplotlib.pyplot as plt
np.random.seed(19680801)
mu, sigma = 100, 15
x = mu + sigma * np.random.randn(10000)
fig, axs = plt.subplots(2,1)
for ax in axs:
n, bins, patches = ax.hist(x, 50, normed=1, facecolor='g', alpha=0.75)
ax.set_ylabel('Probability $y$')
ax.grid(True)
ax.set_yticklabels([ r'\$\num{{{:g}}}\$'.format(item) for item in ax.get_yticks().tolist() ])
fig.show()
I tried this, but it does not work:
fig.canvas.draw()
ylabelposition = ax.yaxis.label.get_position()
ax.set_yticklabels([ r'\$\num{{{:g}}}\$'.format(item) for item in ax.get_yticks().tolist() ])
ax.yaxis.label.set_position(ylabelposition)

Related

Plotting of empty 2D histogram gives unexpected point

When I plot an empty 2D histogram I get an unexpected point in the middle of the plot and am not sure why
max = 100
x = np.zeros(10000)
y = np.zeros(10000)
heatmap, xAxis, yAxis = np.histogram2d(x, y, bins=max)
fig, (ax1, ax2) = plt.subplots(1, 2)
ax1.imshow(heatmap, interpolation='none')
ax2.imshow(convolve(heatmap, Gaussian2DKernel(x_stddev=sigma)), interpolation='none')
plt.show()
Resulting plot
Matplotlib plot is correct. Your data is all 0's
x = np.zeros(10000)
y = np.zeros(10000)
so your histogram will have only one point, (0, 0) with a strictly positive value, 1. All other points will be 0.
This is exactly what you have on your left-hand side plot!
To set correct values on the axis, please follow the snippet below:
import matplotlib.pyplot as plt
import numpy as np
max_ = 100
x = np.zeros(10000)
y = np.zeros(10000)
heatmap, xAxis, yAxis = np.histogram2d(x, y, bins=max_)
fig, (ax1, ax2) = plt.subplots(1, 2)
ax1.axis([min(xAxis), max(xAxis), min(yAxis), max(yAxis)])
ax1.set_aspect(1)
ax1.pcolormesh(xAxis, yAxis, heatmap)
plt.show()

Continuous color scale and nice range with pyplor LogLocator

I am trying to get a continuous color scale in matplotlib for a log plot. But I also want to preserve the nice tick structure and upper and lower limits in the colorbar.
I can only figure out how to do one or the other.
Here the code that generates the two versions
import matplotlib.ticker as ticker
import numpy as np
x = np.linspace(1,200, 50)
y = np.linspace(1,300, 50)
z = np.outer(y, x)
bounds = [np.amin(z), np.amax(z)]
bounds = np.log10(bounds)
bounds[0] = np.floor(bounds[0])
bounds[1] = np.ceil(bounds[1])
bounds = np.power(10, bounds)
fig, ax = plt.subplots()
tickLocator = ticker.LogLocator()
CS = ax.contourf(x, y, z, locator=tickLocator)
ax.set_title("Not enough color bar levels")
cbar = plt.colorbar(CS)
fig, ax = plt.subplots()
tickLocator = ticker.LogLocator(subs=range(1, 10))
CS = ax.contourf(x, y, z, locator=tickLocator)
ax.set_title("Labels missing and not enough range in color bar")
cbar = plt.colorbar(CS)
print("Boundary values")
print(bounds)
print("Tick values")
print(cbar.get_ticks())
plt.show()
With the first version I get nice end points for the ticks, but the levels are very coarse.
With the second version most of the tick labels are missing and the highest tick is smaller than the biggest value in the array.
I found something that works for me by using pcolormesh instead of contourf.
Here the code and output for anyone with a similar problem
import matplotlib.pyplot as plt
import matplotlib.colors as colors
import numpy as np
x = np.linspace(1,200, 200)
y = np.linspace(1,300, 200)
z = np.outer(y, x)
bounds = [np.amin(z), np.amax(z)]
bounds = np.log10(bounds)
bounds[0] = np.floor(bounds[0])
bounds[1] = np.ceil(bounds[1])
bounds = np.power(10, bounds)
fig, ax = plt.subplots()
CS = ax.pcolormesh(x, y, z, norm=colors.LogNorm(*bounds), shading="auto")
cbar = plt.colorbar(CS, ax=ax)
print("Boundary values")
print(bounds)
print("Tick values")
print(cbar.get_ticks())
plt.show()

How to plot the same x and y axis values as the ones of a given matplot plot?

I want to plot with the same x and y axis values (in a separate subplot) the errorbar that I display in the following way (the errorbar is correlated to the histogram drawn under):
import matplotlib.pyplot as plt
fig, ax1 = plt.subplots()
n, bin_edges, patches = ax1.hist(x, log=True, bins='doane', color='red')
bin_centres = (bin_edges[:-1] + bin_edges[1:]) / 2.
ax1.errorbar(bin_centres, n, fmt='o')
plt.xlabel("X_label")
plt.ylabel("Y_label")
plt.show()

How to change the size of plot with equal aspect ratio?

It seems that I can't have both setting equal axes scales AND setting the size of the plot. What I'm doing is:
fig = pl.figure(figsize=(20,20))
ax = fig.add_subplot(111)
ax.set_aspect('equal')
If I remove the figsize the plot seems to have equal scales, but with figsize I have a bigger plot but the scales aren't equal anymore.
Edit: The graph does not necessarily have to be square, just bigger.. please assume that I don't now the exact ratio of the axes
Any solutions?
Thanks
If you want to change the data limits to make the axes square, add datalim to your call to set_aspect:
ax.set_aspect('equal', 'datalim')
If you want the scaling to change so that the limits are different but the axes look square, you can calculate the axis size ratio and set it explicitly:
ax.set_aspect(1./ax.get_data_ratio())
e.g.
import numpy as np
import matplotlib.pyplot as plt
fig = plt.figure(figsize=(7,7))
ax = fig.add_subplot(111)
x = np.linspace(0,np.pi,1000)
y = np.sin(3*x)**2
ax.plot(x,y)
ax.set_aspect('equal', 'datalim')
plt.show()
or
import numpy as np
import matplotlib.pyplot as plt
fig = plt.figure(figsize=(7,7))
ax = fig.add_subplot(111)
x = np.linspace(0,np.pi,1000)
y = np.sin(3*x)**2
ax.plot(x,y)
ax.set_aspect(1./ax.get_data_ratio())
plt.show()

How to add space for xticklabels in python?

all, I'm using Matplotlib to plot a polarbar. But the ticks are overlapped.
Does anybody know how to avoid this? Thanks!
from pylab import *
import matplotlib.pyplot as plt
from cf.plot import BoundaryNorm,getBoundCmap
from matplotlib import colors
fig = figure(figsize=(8,8))
ax = fig.add_axes([0.1, 0.1, 0.8, 0.8], polar=True)
N = 8
theta = np.arange(0.0, 2*np.pi, 2*np.pi/N)
radii = ones((1,N)).squeeze()
width = 2*np.pi/N
bars = ax.bar(theta, radii, width=width, bottom=0.6)
listBnd = [0,3,6,9,12,15,18,21,24]
mcolors = plt.cm.Spectral(linspace(0,1,N))
cmap = colors.ListedColormap(mcolors)
for r,bar in zip(arange(1,N+1), bars):
bar.set_facecolor(cmap(r-1))
xlabels = array([0,21,18,15,12,9,6,3])
ax.xaxis.labelpad=50
ax.set_xticks(theta)
ax.set_xticklabels(xlabels,rotation=270,fontsize='60')
ax.xaxis.set_label_coords(0.5,-0.5)
ax.set_yticklabels([])
grid([])
show()
First off, let's clean up your code a bit. You have a lot of things that don't make sense. (For example, why generate a list of colors from the colormap, then create another colormap, then get the colors you originally generated from the other colormap?)
In addition, you're setting a lot of parameters that probably don't do what you think they do. (For example, the labelpad for an axis controls the padding for the axis label (e.g. xlabel), not for the ticks.)
With that in mind, your code might look something like this:
import numpy as np
import matplotlib.pyplot as plt
fig = plt.figure(figsize=(8,8))
ax = fig.add_subplot(111, projection='polar')
N = 8
theta = np.arange(0.0, 2*np.pi, 2*np.pi/N)
radii = np.ones(N)
width = 2 * np.pi / N
bars = ax.bar(theta, radii, width=width, bottom=0.6)
colors = plt.cm.Spectral(np.linspace(0, 1, N))
for color, bar in zip(colors, bars):
bar.set_facecolor(color)
xlabels = np.array([0,21,18,15,12,9,6,3])
ax.set_xticks(theta)
ax.set_xticklabels(xlabels, rotation=270, fontsize=60)
ax.set_yticklabels([])
ax.grid(False)
plt.show()
Which generates a figure similar to the following:
Basically, you want to use the frac kwarg to ax.set_thetagrids to change the radial position of the theta tick labels. (This is a bit hidden, but it's the easiest way to do it.)
In addition, I'm using fig.tight_layout to resize things so that the tick labels don't wind up outside of the figure boundaries.
import numpy as np
import matplotlib.pyplot as plt
fig = plt.figure(figsize=(8,8))
ax = fig.add_subplot(111, projection='polar')
N = 8
theta = np.arange(0.0, 2*np.pi, 2*np.pi/N)
radii = np.ones(N)
width = 2 * np.pi / N
bars = ax.bar(theta, radii, width=width, bottom=0.6)
colors = plt.cm.Spectral(np.linspace(0, 1, N))
for color, bar in zip(colors, bars):
bar.set_facecolor(color)
xlabels = np.array([0,21,18,15,12,9,6,3])
ax.set_thetagrids(np.degrees(theta), xlabels, frac=1.2,
rotation=270, fontsize=60)
ax.set_yticklabels([])
ax.grid(False)
fig.tight_layout()
plt.show()

Categories

Resources