Не удается выровнять ось по правому краю на MatPlotLib 3d

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

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

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

Не удается выровнять ось по правому краю на MatPlotLib 3d

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

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

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

Не удается выровнять ось по правому краю на MatPlotLib 3d

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

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

Не удается выровнять ось по правому краю на MatPlotLib 3d

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

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

Не удается выровнять ось по правому краю на MatPlotLib 3d

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) ОБНОВИТЬ: согласно приведенному ниже разговору с @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))

Не удается выровнять ось по правому краю на MatPlotLib 3d

Второй аргумент set_yticks - это логическое значение, указывающее, является ли первый аргумент второстепенными тиками. Кажется, нет никакого смысла использовать список в качестве второго аргумента. Однако настоящая проблема здесь не может быть решена, потому что мы просто не знаем фактических единиц данных ваших столбцов. См. минимальный воспроизводимый пример.

ImportanceOfBeingErnest 18.12.2018 11:16

Вы можете увидеть фактические единицы данных полос в примере, но это также не имеет значения. Любые значения дают одинаковые результаты. Проблема не в полосах, а в значениях оси, и я предоставляю эту информацию в своем описании выше. Вы правы насчет set_yticks (отличного от plt.yticks ()), но удаление этого аргумента дает еще более ужасные результаты. Он буквально перестает считать ось на полпути

Elliptica 18.12.2018 11:24

Если буквально любое значение дает одинаковые результаты, это будет сутью проблемы. Но я не могу воспроизвести это. Я не вижу изображения, на котором вы утверждаете, что не использовали никаких модификаций оси, поэтому нет, я не могу «увидеть фактические единицы данных полос в примере».

ImportanceOfBeingErnest 18.12.2018 11:26

Я добавил свой код выше, чтобы вы могли видеть. Вы можете выбрать любые значения для x, y, z, если они попадают в определенные мной диапазоны меток.

Elliptica 18.12.2018 11:40

Без фактических данных единственным ответом является тот тривиальный факт, что вы можете установить галочки через ax.set_yticks(np.arange(0,90,5)).

ImportanceOfBeingErnest 18.12.2018 12:35

Я действительно не понимаю, чего еще вы хотите, поскольку все дело в том, что НЕ имеет значения, какие данные, проблема та же. Если вам ДЕЙСТВИТЕЛЬНО нужны значения, используйте x = [15,28,20], y = [30,50,80], z = [1,1,1]. Но дело в том, что вы можете использовать три значения, которые я предоставил, 100 значений или пустые данные. Это не имеет значения, потому что я говорю не о столбцах, а о рендеринге оси графика. Вы определенно должны суметь это воспроизвести. Если вы хотите попробовать конкретные значения, используйте три, которые я предоставил, но это буквально не имеет значения.

Elliptica 20.12.2018 06:40
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
1
6
849
2

Ответы 2

Как уже говорилось, вы можете установить галочки через 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.

Это правда, но проблема, которая вызвала у меня первоначальный вопрос, заключается в том, что при таком подходе ярлыки, как правило, очень плохо выровнены. Например, обратите внимание, что 85 находится немного впереди своей отметки (это легче увидеть на самом первом изображении графика, которое я включил, но его можно увидеть и на вашем). Невозможно настроить выравнивание с помощью set_yticks, нужно использовать set_ylabels. Однако это создает вышеупомянутые проблемы. Я изо всех сил пытаюсь найти перестановку инструкций, которые 1) устанавливают y-метки и 2) устанавливают выравнивание меток метки, не вызывая проблем.

Elliptica 20.12.2018 15:47

Ммм, я имею в виду, что вы все еще можете добавить ax.set_yticklabels(ax.get_yticks(), verticalalignment='baseline', horizontalalignment='left') в код в ответе, если хотите ?!

ImportanceOfBeingErnest 20.12.2018 16:59

Я сделал, вот в чем вопрос. Вы можете увидеть, как это выглядит на графике.

Elliptica 20.12.2018 17:41

Я немного запутался в том, какая команда, по вашему мнению, что именно делает. Я только что обновил свой ответ этой строкой и полученным графиком.

ImportanceOfBeingErnest 20.12.2018 17:45

Спасибо за терпение, я скопировал ваш код (только что добавил ax.set_xticks(xTicks)), но он разрешается по-другому. Во-первых, ваш график заканчивается на 16 (по оси x), хотя код устанавливает диапазон, начинающийся с 0, а мой - на 0. Однако мой не окрашивает всю ось, только насколько далеко. как есть данные. Пожалуйста, просмотрите обновление моего вопроса, чтобы увидеть, что я вижу.

Elliptica 20.12.2018 18:23

Ну, вы установили некоторые отметки, которые, как кажется, выходят за пределы оси.

ImportanceOfBeingErnest 20.12.2018 18:40

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

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)

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

Другие вопросы по теме