Блокнот Jupyter удаляет левое пустое пространство в matplotlib

Следующий код должен отображать смещение «ax» вправо (перекрывающееся «ax1») с дополнением слева (там, где оно было изначально).

# Implementation of matplotlib function 
import matplotlib.pyplot as plt 
import numpy as np 
from matplotlib.colors import LogNorm 

Z = np.random.rand(6, 30) 

fig, (ax, ax1) = plt.subplots(1, 2) 

ax.pcolor(Z) 
ax1.pcolor(Z) 

chartBox = ax.get_position() 
ax.set_position([chartBox.x0 + chartBox.width / 2,
                chartBox.y0, 
                chartBox.width, 
                chartBox.height]) 

ax.set_title("Original Window") 
ax1.set_title("Modified Window")

plt.show()

Однако в блокноте Jupyter (проверено на vscode и colab) левое пустое пространство обрезано, но при запуске сценария в файле .py оно отображается правильно. Как я могу решить эту проблему?

Оба протестированы на версии Python 3.12 в vscode (jupyterlab==4.1.6) и в терминале с matplotlib==3.8.4. Изменение plt.show() на plt.savefig() приводит к появлению пустого места слева (даже внутри записной книжки). Я подозреваю, что рендеринг из записной книжки неисправен, но я не знаю точных настроек.

Вот что отображает блокнот Jupyter:

Вот что отображает тот же код, запущенный в файле сценария .py:

Контекст

Я перебирал некоторые данные и хотел отобразить несколько графиков 2 на 2, при нечетном сочетании я хотел отобразить один график по центру и отключить второй пустой график. Идея заключалась в том, чтобы использовать .subplots(nrows=1,ncols=2) (потому что у меня не было другой идеи) и сместить первый участок вправо с помощью ax.set_position(). Как оказалось, это не сработало.

«но при запуске сценария в файле .py он отображает его правильно». Возможно, это так; однако вы не указываете, какая версия Python и задействованные пакеты используются в случае, если вы запускаете его как сценарий, а не в Jupyter. Окружающая среда, вероятно, другая и поможет решить вашу проблему. Когда я запускаю его в Jupyter, а затем как скрипт на том же Python, где я сохраняю файл, используя plt.savefig("test_fig.png") вместо plt.show(), я вижу то же самое. А именно, ось «Модифицированное окно» переместилась влево, так что она перекрывает «Исходное окно»....

Wayne 06.05.2024 16:29

<продолжение> примерно на уровне значения 20 на подграфике «Исходное окно». График «Исходное окно» остается привязанным к левой границе независимо от того, включаю ли я часть ax.set_position() или нет. Что касается «Идея заключалась в том, чтобы использовать .subplots(nrows=1,ncols=2) (потому что у меня не было другой идеи) и сместить первый график вправо с помощью ax.set_position()». Это само определение XY-проблема, которую вы создали. Возможно, вы на правильном пути; однако, что вы на самом деле пытаетесь здесь решить. Проблема, о которой вы писали до предпоследнего предложения? Или ...

Wayne 06.05.2024 16:37

<продолжение> Какова, по вашему мнению, была ваша первоначальная цель? А пока вы можете просто уточнить в комментариях, чтобы мы обращались к правильному вопросу. Честно говоря, на данный момент я не знаю, были ли вы на правильном пути или нет, используя тот подход, который вы пробуете. Но если настоящая цель — «Идея», то я не буду стараться максимально придерживаться того, что у вас есть, и не рассматривать другие подходы.

Wayne 06.05.2024 16:40

Это правда, что я хочу сделать X (иметь центрированный график по горизонтали), а не Y (чтобы левое пустое пространство не было обрезано блокнотом Jupyter), однако после непродолжительного поиска в Google я не нашел никого, обращающегося к Y, и я подумал что я был настолько разочарован попыткой Y, что стоило выслушать сообщество по этому вопросу, потому что я предполагал, что кто-то в обозримом будущем наткнется на Y и найдет это полезным.

Sheed 06.05.2024 17:18

@Уэйн, я добавил некоторую информацию, но «сюжет «Исходное окно» остается привязанным к левой границе, независимо от того, включаю ли я часть ax.set_position() или нет». у вас есть эта проблема даже при запуске файла .py?

Sheed 06.05.2024 17:24

Да, когда я запускаю его как Python, он тоже остается слева. Однако я на 100% уверен, что оба используют один и тот же Python и пакеты в моей системе. Я в этом не уверен, учитывая, что вы видите разные результаты. Или, может быть, это связано с тем, что в вашей системе серверная часть отличается от Python в командной строке и в Jupyter? (На самом деле вы не указываете, в каком бэкэнде вы его видите, когда запускаете его как скрипт Python.) В моем случае я разрешаю ему сохранять только рисунок графика, потому что нет другого выбора для графического бэкэнда, над которым я работаю. облако в настоящее время.

Wayne 06.05.2024 17:29

Серверной частью графического пользовательского интерфейса является TkAgg, а серверной частью savefig() является значение по умолчанию (то есть agg согласно документации). На моей стороне оба показывают пустое место слева (даже при вызове plt.savefig() из записной книжки). Так что очень странно, что у вас другое поведение

Sheed 06.05.2024 17:42

«даже при вызове plt.savefig() из записной книжки» О, если я правильно понимаю, это, похоже, исключает мое предположение, что это разные версии. Итак, когда вы запускаете код, вы видите, что он привязан к левой стороне вывода блокнота, но при использовании plt.savefig() в том же блокноте он добавляет отступы?

Wayne 06.05.2024 17:49

Да, именно, во всех случаях есть отступ, за исключением использования plt.show() внутри блокнота, где он прикрепляется к левой стороне окна. Я не совсем понимаю, почему у вас нет отступа даже при звонке plt.savefig(). Потому что я предполагаю, что проблема в том, как блокнот Jupyter отображает matplotlib, но ваш случай подсказывает мне, что это может быть что-то другое.

Sheed 06.05.2024 17:59

Теперь я получил хорошее преимущество в том, что прокладка не отображается. Я опубликовал ответ, поскольку он довольно сложен и требует кода. Кроме того, я смотрю на то, что получаю от plt.savefig(), и слева от «исходного окна» есть отступы. Что касается вашей последней части комментария: «Я не совсем понимаю, почему у вас нет отступов даже при вызове plt.savefig()». Я тогда не видел вашего обновленного сообщения и понял, что это отрезание отступов. Я вижу прокладку. В своих первых двух постах я был сосредоточен на движении двух графиков и не осознавал, что отступы — это то, что вам тоже нужно. Извини.

Wayne 06.05.2024 18:30

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

Wayne 06.05.2024 18:50
Почему в 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 может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
0
11
127
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

В наши дни, если вы ничего не указываете, то %matplotlib inline — это серверная часть по умолчанию. А встроенное значение по умолчанию для bbox_inches в наши дни — tight. Я вернусь к этому через минуту. Итак, один из вариантов - сделать это не inline. Если вы перейдете сюда и щелкните значок «launch binder» (значки внизу позволяют выбрать конкретную версию Jupyter), вы получите сеанс, в котором ipympl установлен с современными версиями Jupyter. Таким образом, вы можете добавить %matplotlib ipympl в качестве первой строки вверху кода, который затем вставите в новую ячейку, запустите ее и увидите, что теперь есть отступы. (Если у вас еще не установлен ipympl, вам нужно сначала установить его и правильно обновить/перезапустить все, чтобы использовать его в качестве серверной части. Некоторые говорят, что обновления страницы браузера достаточно; однако я бы предложил перезапустить все [браузер , Jupyter и ваша машина], если можете, поскольку это добавляет множество возможностей на многих уровнях вашей технологии.) Вы можете убедиться, что это удалось, перезапустив ядро ​​и добавив # перед %matplotlib ipympl, чтобы прокомментировать первую строку, и перезапустить код. Он должен вернуться во встроенный режим с bbox_inches как tight, чтобы крайний левый график придерживался левой границы.

В качестве альтернативы вы можете использовать настройку встроенной поддержки для отключения bbox_inches='tight'

Поскольку при встроенной настройке bbox_inches по умолчанию используется как tight, вы можете продолжать использовать встроенный бэкэнд; однако настройте его так, чтобы он не был установлен на tight.

Итак, в своем блокноте создайте новую ячейку и выполните следующее:

%config InlineBackend.print_figure_kwargs = {'bbox_inches':None}`

После этого попробуйте исходный блок кода как есть, и теперь вы должны увидеть отступы.

Атрибуция:
На основании комментариев и нижней части этого ответа там же , где конкретно упоминается «встроенный бэкэнд» и этого ответа здесь на вопрос «Как отключить bbox_inches='tight» при работе со встроенным matplotlib в блокнот ipython'

%matplotlib ipympl требует pip install ipympl, но plt.show() возвращает ошибку javascript, где написано «Ошибка: ни одна версия модуля jupyter-matplotlib не зарегистрирована». Он запросил загрузить какой-то пакет. А трассировка стека показывает ссылки вдоль линии *.vscode-resource.vscode-cdn.net. Поэтому я считаю, что проблема в том, что vscode не находит сторонний виджет. Он работает в colab (хотя вам нужно добавить from google.colab import output; output.enable_custom_widget_manager()). В качестве альтернативы ваш второй подход работает как в colab, так и в vscode. Вы молодцы!
Sheed 06.05.2024 18:41

Да, я обновил, чтобы упомянуть, что если у вас его нет, вам нужно его установить. Я упоминаю, куда я послал вас, чтобы оно было установлено. Однако я не вижу этой ошибки и поэтому не думаю, что вы еще должным образом обновили все после установки. То, с чем вы столкнулись, похоже на мой обмен мнениями из этого пункта в некоторых связанных комментариях и далее. Вы увидите, что обновление/перезапуск было галочкой. Я думаю, что вы попадаете в это.

Wayne 06.05.2024 18:54

да, действительно, мне пришлось перезапустить vscode, или, может быть, это были какие-то проблемы с Интернетом.

Sheed 06.05.2024 18:55

Я не думаю, что это был Интернет. ipympl многое добавляет, поэтому обновления в настройках и изменениях необходимо полностью распространять. Я тоже попытался уточнить это в ответе. Настройка bbox_inches проще; однако знание ipympl поможет большему количеству людей в современном использовании Jupyter в наши дни, учитывая, что поздние версии JupyterLab 3 и выше, а также Jupyter Notebook 7+ сейчас нуждаются в нем для многих вещей.

Wayne 06.05.2024 18:58

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