Не могу заставить ось выравниваться прямо на MatPlotLib 3d - PullRequest
0 голосов
/ 18 декабря 2018

Я пытаюсь сделать 3D-график.У меня возникают проблемы с отображением полной оси с хорошо выровненными метками.Я обрисовал в общих чертах шаги, которые я попробовал ниже.

1) Я могу установить метки оси Y, используя:

yTicks = list(range(0,90,5)
ax.set_yticks(range(len(yTicks)), True)

enter image description here

Однако, как видите, метки очень плохо выровнены.Это также не соответствует тому, что я на самом деле определил, что должно было быть подсчетом тиков на 5, а не на 10.

2) Однако, если я попробую также использовать set_yticklabels, выравнивание будет исправлено, но онопечатает только часть оси.Вот код и изображение:

ax.set_yticklabels(yTicks, verticalalignment='baseline', horizontalalignment='left')

enter image description here

Обратите внимание, как ось Y изменилась с 80 до 40.

3) И если я избавлюсь от True в set_yticks, все вместе сжимается:

enter image description here

4) Наконец, если я использую и set_yticks, и set_yticklabels, вызывая get_yticks() в функции меток, это почти работает, но вы можете видеть, что линии осей выходят за "поверхность" графика:

ax.set_yticks(range(len(yTicks)), True)
ax.set_yticklabels(ax.get_yticks(), verticalalignment='baseline',
               horizontalalignment='left')

enter image description here

5) Вот более полная версия моего кода для справки:

plt.clf()

ax = plt.axes(projection='3d')

ax.bar3d(x,y,z, 
     1,1,[val*-1 if val != 0 else 0 for val in z])

xTicks = list(range(0,25,2))
yTicks = list(range(30,90,5))

ax.set_zlim(0, 1)

ax.set_xticks(range(len(xTicks)), True)
ax.set_yticks(range(len(yTicks)), True)

ax.set_xticklabels(ax.get_xticks(), 
                verticalalignment='baseline',
                horizontalalignment='left')

ax.set_yticklabels(ax.get_yticks(), 
                verticalalignment='baseline',
                horizontalalignment='left')

plt.savefig(file_path)

Как мне заставить его показать мою полную ось (0-90) с интервалами 5 и хорошо ли он выровнен?

6) UPDATE : в соответствии с приведенным ниже разговором с @ImportanceOfBeingErnest, вот проблема, с которой я все еще сталкиваюсь, используя следующий код:

x=[15,28,20]; y=[30,50,80]; z=[1,1,1]

plt.clf()

ax = plt.axes(projection='3d')

ax.bar3d(x,y,z, 
         1,1,[val*-1 if val != 0 else 0 for val in z])

xTicks = list(range(0,25,2))
yTicks = list(range(30,90,5))
ax.set_xticks(xTicks)
ax.set_yticks(yTicks)

ax.set_yticklabels(ax.get_yticks(), 
                verticalalignment='baseline',
                horizontalalignment='left')

ax.set_zlim(0, 1)

plt.savefig(getSaveGraphPath(save_name))

enter image description here

Ответы [ 2 ]

0 голосов
/ 21 декабря 2018

Таким образом, после долгих проб и ошибок единственный способ, которым я мог бы заставить график правильно отображать оси в различных предельных случаях, заключается в следующем.Я не совсем доволен этим (обратите внимание, что последний ярлык y-тика не отображается), но это единственная версия, в которой цифры фактически стоят рядом с их отметками).Я должен был позволить ограничения x и y быть эффективными, только если данные не превышали их значения, тогда как граница z является жестким ограничением.Я не утверждаю, что понимаю, почему все эти перестановки необходимы (это всего лишь проблема с 3D-графикой), но это решение, которое работает для меня:

plt.clf()

ax = plt.axes(projection='3d')

# Need to force include fake NaN data at the axis limits to make sure labels
# render correctly
#
# xLims and yLims create boundaries only if data doesn't stretch beyond them

xstart, xend = xLims
ystart, yend = yLims
x = [xstart] + x + [xend]
y = [ystart] + y + [yend]
z = [numpy.nan] + z + [numpy.nan]

# Plot graph

ax.bar3d(x,y,z,1,1,[val*-1 if val != 0 else 0 for val in z])

# Set z boundary (after graph creation)

ax.set_zbound(zBounds)

# Need to adjust labels slightly to make sure they align properly

use_x_ticks = ax.get_xticks()

### ON SOME SYSTEMS, use_x_ticks = ax.get_xticks()[1:] is needed for correct alignment ###

ax.set_xticklabels([int(x)  if x==int(x) else x for x in use_x_ticks],
                    horizontalalignment='right',
                    verticalalignment='baseline')

ax.set_yticklabels([int(y) if y==int(y) else y for y in ax.get_yticks()],
                    verticalalignment='top')

# Save graph

plt.savefig(file_save_path)

Как вы можете видеть ниже,все хорошо выровнено:

enter image description here

0 голосов
/ 20 декабря 2018

Как прокомментировано, вы можете установить тики с помощью ax.set_yticks.

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

x=[15,28,20]; y=[30,50,80]; z=[1,1,1]

ax = plt.axes(projection='3d')

ax.bar3d(x,y,z, 
     1,1,[val*-1 if val != 0 else 0 for val in z])


yTicks = list(range(30,90,5))
ax.set_yticks(yTicks)

ax.set_yticklabels(ax.get_yticks(), 
                verticalalignment='baseline',
                horizontalalignment='left')

ax.set_zlim(0, 1)

plt.show()

Это покажет желаемые 5 единичных шагов по оси Y.

enter image description here

...