3

I'm plotting a set of 3d coordinates (x,y,z) using Axes3D. My code reads

import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D

x,y,z=data[::1,0],data[::1,1],data[::1,2]
fig=plt.figure(figsize=(10,10))
ax=fig.add_subplot(111,projection='3d')
ax.scatter(x,y,z,s=0.1,c=z,cmap='hot',marker='+')
plt.show()

I want all three axes to have the same scaling. Now, the problem is that the data has a large aspect ratio, that is, the variation in the x and y coordinates is about 10 times larger than the variation in the z coordinate. If I put

mi=np.min(data)
ma=np.max(data)    
ax.set_xlim(mi,ma)
ax.set_ylim(mi,ma)
ax.set_zlim(mi,ma)

this will result in uniformly scaled axes but will waste a lot of space in the z direction. How can I avoid this and get uniformly scaled axes nevertheless?

Trenton McKinney
  • 56,955
  • 33
  • 144
  • 158
phlegmax
  • 419
  • 1
  • 4
  • 11
  • Do you want your axes to have the same scale? Or to be of the same size? – nicoguaro Mar 17 '15 at 13:59
  • I want them to have the same scale. Then, as I have non uniformly distributed data and don't want to waste space in the plot I will have axes of very different length. – phlegmax Mar 17 '15 at 15:31

1 Answers1

2

There is a question in SO that is similar... but I cannot find it. So I am attaching some code for what I understand is your problem (the part that scales is not mine, but from that other post I mentioned)

import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D

data =np.random.rand(100,3)

x,y,z= 10*data[:,0], 20*data[:,1], 5*data[:,2]
fig=plt.figure(figsize=(10,10))
ax=fig.add_subplot(111,projection='3d')
ax.scatter(x,y,z)

# Fix aspect ratio
max_range = np.array([x.max()-x.min(), y.max()-y.min(),
                      z.max()-z.min()]).max() / 2.0
mean_x = x.mean()
mean_y = y.mean()
mean_z = z.mean()
ax.set_xlim(mean_x - max_range, mean_x + max_range)
ax.set_ylim(mean_y - max_range, mean_y + max_range)
ax.set_zlim(mean_z - max_range, mean_z + max_range)

plt.show()

And, this is the result:

enter image description here

nicoguaro
  • 3,629
  • 1
  • 32
  • 57
  • Unfortunately, this is not quite what I'm looking for. This way I always get a cubic plot, that is, all axes have the same length. However, I want the three axes to have the same scaling, that is, I want the little tiles in the background of the plot to be cubic (like in your example), but on the other hand, I want each axis not to be longer than necessary for plotting the data. In your example, I would want to z-axis to range, say, from -3 to 7 only. – phlegmax Mar 17 '15 at 18:53
  • Oh, ok, next time you can add a plot of what you want. Sorry, I don't know how to do what you want. I think that there is not an easy way, because there are some things hardcoded in `mplot3d`. I suggest you to ask in the mail list or gitter chat of `matplotlib`. – nicoguaro Mar 17 '15 at 19:20