Hey I cannot figure out any solution to solve my problem. The first tick labels keep overlapping. I found some methods to pad the tick label, but they did not work for a 3D plot.
Is there any way to solve this?
You can directly position and give the tick labels. If you are short on size consider setting the ticks yourself (alignment, position, names, font size, etc.). The following example does this for the Y axis tick labels:
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
import numpy as np
fig = plt.figure(figsize=(10,10))
ax = fig.gca(projection='3d')
x,y,z = np.random.randint(0,100,30),np.random.randint(0,100,30),np.random.randint(0,100,30)
ax.scatter(x,y,z)
ax.set_xlabel('X')
ax.set_xlim3d(0, 100)
ax.set_ylabel('Y')
ax.set_ylim3d(0, 100)
ax.set_yticks([30,60,90])
ax.set_yticklabels(['number 30','number 60','number 90'], va='center', ha='left',fontsize=24)
ax.set_zlabel('Z')
ax.set_zlim3d(0, 100)
plt.show()
, this results in:
Obviously you'll need to see what works for the figure size you want and the values you want to be shown in your plot.
Related
I have a problem with shifting the label of z axis in z direction (along the axis) in 3d plot. I want to have the label of Z-axis at its end. I found that it should be possible for example by ax.zaxis.set_label_coords(0,0,10) but it does not work.
I am using the following code to generate the plot:
from mpl_toolkits.mplot3d import Axes3D
%matplotlib notebook
fig = plt.figure(figsize=(10,7))
ax = fig.gca(projection='3d')
ax.xaxis.set_rotate_label(False)
ax.set_xlabel(r'$X$',fontsize=16,rotation=0)
ax.set_xlim3d(0, 9)
ax.yaxis.set_rotate_label(False)
ax.set_ylabel(r'$Y$',fontsize=16,rotation=0)
ax.set_ylim3d(0.35, 0.58)
ax.zaxis.set_rotate_label(False)
ax.set_zlabel(r'$Z$',fontsize=16,rotation=0, labelpad=5)
ax.zaxis.set_label_coords(0,0,10)
ax.set_zlim3d(0, 10)
ax.view_init(elev=30., azim=220)
plt.show()
Though I have no idea why set_label_coords() doesn't work in 3d plot, you can use ax.text() instead to draw the z label.
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
fig = plt.figure(figsize=(10,7))
ax = fig.gca(projection='3d')
ax.xaxis.set_rotate_label(False)
ax.set_xlabel(r'$X$',fontsize=16,rotation=0)
ax.set_xlim3d(0, 9)
ax.yaxis.set_rotate_label(False)
ax.set_ylabel(r'$Y$',fontsize=16,rotation=0)
ax.set_ylim3d(0.35, 0.58)
ax.zaxis.set_rotate_label(False)
ax.set_zlabel(r'$Z$',fontsize=16,rotation=0, labelpad=5)
ax.set_zlim3d(0, 10)
ax.text(x=-1, y=0.58, z=11, s="z", color='red', size=8)
ax.view_init(elev=30., azim=220)
plt.show()
There are already some questions about set_label_coords() in 3d plot, but none gives a reason why it doesn't work.
matplotlib - How to adjust position of axis labels in 3D plots
set_label_position no effect in 3d?
I am trying to plot a circle with a grid being shown. I wrote the following script which gives the below picture. However, the labels on the axes are interfering together. How to make the label appear (..,-10,-5,0,5,10,...) KEEPING the grid as it appears in the below figure?. I want to keep the dimension of the grid cell as 1*1 dimension.
I tried to use plt.locator_params(), but the dimension of the grid cell changed and became bigger.
import numpy as np
import matplotlib.pyplot as plt
import math
from matplotlib.pyplot import figure
R1=28
n=64
t=np.linspace(0, 2*np.pi, n)
x1=R1*np.cos(t)
y1=R1*np.sin(t)
plt.axis("square")
plt.grid(True, which='both', axis='both')
plt.xticks(np.arange(min(x1)-2,max(x1)+2, step=1))
plt.yticks(np.arange(min(y1)-2,max(y1)+2, step=1))
#plt.locator_params(axis='x', nbins=5)
#plt.locator_params(axis='y', nbins=5)
plt.plot(x1,y1)
plt.legend()
plt.show()
Not a matplotlib expert, so there may be a better way to do this, but perhaps like the following:
from matplotlib.ticker import MultipleLocator
...
fig, ax = plt.subplots(figsize=(6, 6))
ax.plot(x1,y1)
ax.xaxis.set_minor_locator(MultipleLocator())
ax.xaxis.set_major_locator(MultipleLocator(5))
ax.yaxis.set_minor_locator(MultipleLocator())
ax.yaxis.set_major_locator(MultipleLocator(5))
ax.grid(True, which='both', axis='both')
plt.show()
If I do rotation to the colorbar labels, the format I used seem to be reset (ignored).
The fig.colorbar does not accept rotation, while cb.ax.set_xticklabels does not accept format.
I couldn't find any way to do both settings.
import numpy as np
from matplotlib import pyplot as plt
from matplotlib.ticker import FormatStrFormatter
test = np.random.rand(100, 100)
np.random.seed(12345)
fig, axs = plt.subplots(1, 2, figsize=(6, 5))
fmts = ["%d", "%.5f"]
for i, ax in enumerate(axs.tolist()):
im = ax.imshow(test, origin="lower")
cb = fig.colorbar(im, ax=ax, orientation='horizontal',
format=FormatStrFormatter(fmts[i]))
ax.set_title(f"Format {fmts[i]}")
cb.ax.set_xticklabels(cb.get_ticks(), rotation=45)
plt.tight_layout()
plt.show()
The colorbar tick labels should be in the format of "%d" and "%.5f" but as you can see, neither does.
I don't think that the original formatting is kept when you call cb.ax.set_xticklabels(), you could add cb.ax.xaxis.set_major_formatter(FormatStrFormatter(fmts[i])) to re-apply the custom formatting afterwards.
As an alternative, use plt.setp(cb.ax.get_xticklabels(),rotation=45) instead to rotate the labels.
I have multiple plots that have the same x-axis. I would like to stack them in a report and have everything line up. However, matplotlib seems to resize them slightly based on the y tick label length.
Is it possible to force the plot area and location to remain the same across plots, relative to the pdf canvas to which I save it?
import numpy as np
import matplotlib.pyplot as plt
xs=np.arange(0.,2.,0.00001)
ys1=np.sin(xs*10.) #makes the long yticklabels
ys2=10.*np.sin(xs*10.)+10. #makes the short yticklabels
fig=plt.figure() #this plot ends up shifted right on the canvas
plt.plot(xs,ys1,linewidth=2.0)
plt.xlabel('x')
plt.ylabel('y')
fig=plt.figure() #this plot ends up further left on the canvas
plt.plot(xs,ys2,linewidth=2.0)
plt.xlabel('x')
plt.ylabel('y')
Your problem is a little unclear, however plotting them as subplots in the same figure should gaurantee that the axes and figure size of the two subplots will be alligned with each other
import numpy as np
import matplotlib.pyplot as plt
xs=np.arange(0.,2.,0.00001)
ys1=np.sin(xs*10.) #makes the long yticklabels
ys2=10.*np.sin(xs*10.)+10. #makes the short yticklabels
fig, (ax1, ax2) = plt.subplots(2, 1)
ax1.plot(xs,ys1,linewidth=2.0)
ax1.set_xlabel('x')
ax1.set_ylabel('y')
ax2.plot(xs,ys2,linewidth=2.0)
ax2.set_xlabel('x')
ax2.set_ylabel('y')
plt.subplots_adjust(hspace=0.3) # adjust spacing between plots
plt.show()
This produces the following figure:
I had the same problem. The following works for me.
Force the same figure width for all your plots around all your python scripts, for example:
fig1 = plt.figure(figsize=(12,6))
...
fig2 = plt.figure(figsize=(12,4))
And do not use (very important!):
fig.tight_layout()
Save the figure
plt.savefig('figure.png')
Plot areas should now be the same.
using subplots with the same x-axis should do the trick.
use sharex=True when you create the subplots. The benefit of sharex is that zooming or panning on 1 subplot will also auto-update on all subplots with shared axes.
import numpy as np
import matplotlib.pyplot as plt
xs = np.arange(0., 2., 0.00001)
ys1 = np.sin(xs * 10.) # makes the long yticklabels
ys2 = 10. * np.sin(xs * 10.) + 10. # makes the short yticklabels
fig, (ax1, ax2) = plt.subplots(2, sharex=True)
ax1.plot(xs, ys1, linewidth=2.0)
ax1.xlabel('x')
ax1.ylabel('y')
ax2.plot(xs, ys2, linewidth=2.0)
ax2.xlabel('x')
ax2.ylabel('y')
plt.show()
I am trying to work out how to set/correct the position of tick labels for a 3D matplotlib plot. Tick labels do not align with the ticks. The issue seems to be especially prominent when many tick labels are required.
I have modified an example (http://matplotlib.org/examples/mplot3d/polys3d_demo.html) from the matplotlib documentation to illustrate my question.
from mpl_toolkits.mplot3d import Axes3D
from matplotlib.collections import PolyCollection
from matplotlib.colors import colorConverter
import matplotlib.pyplot as plt
import numpy as np
fig = plt.figure(figsize=(10,10))
ax = fig.gca(projection='3d')
cc = lambda arg: colorConverter.to_rgba(arg, alpha=0.6)
xs = np.arange(0, 10, 0.4)
verts = []
zs = np.arange(50)
for z in zs:
ys = np.ones(len(xs))*z
ys[0], ys[-1] = 0, 0
verts.append(list(zip(xs, ys)))
poly = PolyCollection(verts,facecolor='c')
poly.set_alpha(0.7)
ax.add_collection3d(poly, zs=zs, zdir='y')
ax.set_xlabel('X')
ax.set_xlim3d(0, 10)
ax.set_ylabel('Y')
ax.set_ylim3d(-1, len(zs))
ax.set_yticks(np.arange(len(zs)))
labels = {}
for l_c in zs:
labels[l_c] = 'This Looks Bad'
ax.set_yticklabels(labels,rotation=-15)
ax.set_zlabel('Z')
ax.set_zlim3d(0, ys.max())
plt.show()
So the question is: how can I get the tick labels to align with the tick positions?
By using these alignments, I get much better placements:
ax.set_yticklabels(labels,rotation=-15,
verticalalignment='baseline',
horizontalalignment='left')
I've modified the example with less tick markers so you can see the placement:
They do align, but with the horizontal position centered at the tick. Because of the 3D view this makes them appear a bit below where you would expect them to be. The effect is not related to the amount of ticks but to the width.
Specifically setting the alignment will help. Try adding:
ax.set_yticklabels(labels,rotation=-15, va='center', ha='left')
Play around a bit with the different alignments to see which you prefer, i think you're after ha='left'.
Reducing the padding, distance from the tick, might also help.
You can also set the pad argument as negative in the tick_params options for each axis. Like this:
ax.tick_params(axis='x', which='major', pad=-3)
This might help to adjust the distance between tick labels and axis.