matplotlib (равная единичная длина): с «равным» отношением размеров z-ось не равна x- и y-

Когда я устанавливаю равное соотношение сторон для 3d-графика, ось z не изменяется на «равно». Итак, это:

fig = pylab.figure() mesFig = fig.gca(projection='3d', adjustable='box') mesFig.axis('equal') mesFig.plot(xC, yC, zC, 'r.') mesFig.plot(xO, yO, zO, 'b.') pyplot.show() 

дает мне следующее: введите описание изображения здесь

где, очевидно, единичная длина оси z не равна x- и y-единицам.

Как я могу сделать единицу длины всех трех осей равными? Все решения, которые я мог найти, не сработали. Спасибо.

4 Solutions collect form web for “matplotlib (равная единичная длина): с «равным» отношением размеров z-ось не равна x- и y-”

Я считаю, что matplotlib еще не установил правильную равную ось в 3D … Но я нашел трюк несколько раз назад (я не помню, где), что я адаптировал его. Концепция заключается в создании фальшивой кубической ограничивающей рамки вокруг ваших данных. Вы можете проверить его следующим кодом:

 from mpl_toolkits.mplot3d import Axes3D from matplotlib import cm import matplotlib.pyplot as plt import numpy as np fig = plt.figure() ax = fig.gca(projection='3d') ax.set_aspect('equal') X = np.random.rand(100)*10+5 Y = np.random.rand(100)*5+2.5 Z = np.random.rand(100)*50+25 scat = ax.scatter(X, Y, Z) # Create cubic bounding box to simulate equal aspect ratio max_range = np.array([X.max()-X.min(), Y.max()-Y.min(), Z.max()-Z.min()]).max() Xb = 0.5*max_range*np.mgrid[-1:2:2,-1:2:2,-1:2:2][0].flatten() + 0.5*(X.max()+X.min()) Yb = 0.5*max_range*np.mgrid[-1:2:2,-1:2:2,-1:2:2][1].flatten() + 0.5*(Y.max()+Y.min()) Zb = 0.5*max_range*np.mgrid[-1:2:2,-1:2:2,-1:2:2][2].flatten() + 0.5*(Z.max()+Z.min()) # Comment or uncomment following both lines to test the fake bounding box: for xb, yb, zb in zip(Xb, Yb, Zb): ax.plot([xb], [yb], [zb], 'w') plt.grid() plt.show() 

z на порядок больше, чем x и y, но даже с опцией равной оси, matplotlib автомасштабирует ось z:

Плохо

Но если вы добавите ограничивающий прямоугольник, вы получите правильное масштабирование:

введите описание изображения здесь

Я упростил решение Remy F с помощью set_x/y/zlim .

 from mpl_toolkits.mplot3d import Axes3D from matplotlib import cm import matplotlib.pyplot as plt import numpy as np fig = plt.figure() ax = fig.gca(projection='3d') ax.set_aspect('equal') X = np.random.rand(100)*10+5 Y = np.random.rand(100)*5+2.5 Z = np.random.rand(100)*50+25 scat = ax.scatter(X, Y, Z) max_range = np.array([X.max()-X.min(), Y.max()-Y.min(), Z.max()-Z.min()]).max() / 2.0 mid_x = (X.max()+X.min()) * 0.5 mid_y = (Y.max()+Y.min()) * 0.5 mid_z = (Z.max()+Z.min()) * 0.5 ax.set_xlim(mid_x - max_range, mid_x + max_range) ax.set_ylim(mid_y - max_range, mid_y + max_range) ax.set_zlim(mid_z - max_range, mid_z + max_range) plt.show() 

введите описание изображения здесь

Мне нравятся вышеупомянутые решения, но у них есть недостаток, который вам нужно отслеживать диапазоны и средства по всем вашим данным. Это может быть громоздким, если у вас есть несколько наборов данных, которые будут отображаться вместе. Чтобы исправить это, я использовал методы ax.get_ [xyz] lim3d () и поместил все это в отдельную функцию, которую можно вызвать только один раз, прежде чем вы вызовете plt.show (). Вот новая версия:

 from mpl_toolkits.mplot3d import Axes3D from matplotlib import cm import matplotlib.pyplot as plt import numpy as np def set_axes_equal(ax): '''Make axes of 3D plot have equal scale so that spheres appear as spheres, cubes as cubes, etc.. This is one possible solution to Matplotlib's ax.set_aspect('equal') and ax.axis('equal') not working for 3D. Input ax: a matplotlib axis, eg, as output from plt.gca(). ''' x_limits = ax.get_xlim3d() y_limits = ax.get_ylim3d() z_limits = ax.get_zlim3d() x_range = abs(x_limits[1] - x_limits[0]) x_middle = np.mean(x_limits) y_range = abs(y_limits[1] - y_limits[0]) y_middle = np.mean(y_limits) z_range = abs(z_limits[1] - z_limits[0]) z_middle = np.mean(z_limits) # The plot bounding box is a sphere in the sense of the infinity # norm, hence I call half the max range the plot radius. plot_radius = 0.5*max([x_range, y_range, z_range]) ax.set_xlim3d([x_middle - plot_radius, x_middle + plot_radius]) ax.set_ylim3d([y_middle - plot_radius, y_middle + plot_radius]) ax.set_zlim3d([z_middle - plot_radius, z_middle + plot_radius]) fig = plt.figure() ax = fig.gca(projection='3d') ax.set_aspect('equal') X = np.random.rand(100)*10+5 Y = np.random.rand(100)*5+2.5 Z = np.random.rand(100)*50+25 scat = ax.scatter(X, Y, Z) set_axes_equal(ax) plt.show() 

EDIT: код user2525140 должен работать отлично, хотя этот ответ предположительно попытался исправить несуществующую ошибку. Ответ ниже – это всего лишь дубликат (альтернативная) реализация:

 def set_aspect_equal_3d(ax): """Fix equal aspect bug for 3D plots.""" xlim = ax.get_xlim3d() ylim = ax.get_ylim3d() zlim = ax.get_zlim3d() from numpy import mean xmean = mean(xlim) ymean = mean(ylim) zmean = mean(zlim) plot_radius = max([abs(lim - mean_) for lims, mean_ in ((xlim, xmean), (ylim, ymean), (zlim, zmean)) for lim in lims]) ax.set_xlim3d([xmean - plot_radius, xmean + plot_radius]) ax.set_ylim3d([ymean - plot_radius, ymean + plot_radius]) ax.set_zlim3d([zmean - plot_radius, zmean + plot_radius]) 
  • Рисование эллипсов на проекциях базовой карты matplotlib
  • Отображать несколько mpld3 экспорта на одной странице HTML
  • Matplotlib: получение подзаголовков для заполнения фигуры
  • метка matplotlib не работает
  • Хотите построить Pandas Dataframe в виде нескольких гистограмм с осью x10 по шкале log10
  • Python: subplot внутри цикла: первая панель отображается в неправильном положении
  • Невозможно сохранить анимацию matplotlib с помощью ffmpeg
  • Matplotlib imshow () растянуть до "fit width"
  • matplotlib покажет цифру снова
  • Python / matplotlib mplot3d- как установить максимальное значение для оси z?
  • Аннотировать тепловую карту со значением из кадра данных Pandas
  • Python - лучший язык программирования в мире.