Зменшити лівий і правий поля в графіку matplotlib


178

Я з усіх сил намагаюся розібратися зі своїми сюжетними полями в matplotlib. Я використовував код нижче, щоб створити свою діаграму:

plt.imshow(g)
c = plt.colorbar()
c.set_label("Number of Slabs")
plt.savefig("OutputToUse.png")

Однак я отримую вихідну фігуру з великою кількістю білого простору з обох боків ділянки. Я шукав google і читав документацію на matplotlib, але не можу знайти, як зменшити це.


Є чи ця проблема кількості прогалин у extentчастині imshowмалюнка, або кількість кордонів прогалин в результуючому PNG, навколо фігури, генерується savefig?
unutbu

Я думаю, що і те й інше - здається, що в вікні перегляду і в PNG багато місця Однак важливим результатом є файл png, створений компанією savefig- так що я хотів би сортувати.
robintw

Я щойно згодом обрізав їх у GIMP. : /
endolith

Відповіді:


251

Одним із способів автоматичного зробити це є bbox_inches='tight'кварг plt.savefig.

Напр

import matplotlib.pyplot as plt
import numpy as np
data = np.arange(3000).reshape((100,30))
plt.imshow(data)
plt.savefig('test.png', bbox_inches='tight')

Інший спосіб - використання fig.tight_layout()

import matplotlib.pyplot as plt
import numpy as np

xs = np.linspace(0, 1, 20); ys = np.sin(xs)

fig = plt.figure()
axes = fig.add_subplot(1,1,1)
axes.plot(xs, ys)

# This should be called after all axes have been added
fig.tight_layout()
fig.savefig('test.png')

5
Чи є спосіб зробити це за замовчуванням?
ендоліт

1
Якщо у вас є кілька субплот, і ви хочете зберегти кожен з них, ви можете використовувати і це fig.savefig(). ( plt.savefig()не буде працювати в цьому випадку.)
Абхраніл Дас

1
Все це - це обрізання зображення після його надання; якщо ви намагаєтесь застосувати певну роздільну здатність, зображення вийде меншим .
detly

5
@detly - Так. Саме це і робиться (хоча воно також може «вирізати», а також збільшити зображення). Що ви хочете, погляньте fig.tight_layout(). Ця функція не існувала, коли ця відповідь була написана спочатку, інакше я б її згадував більш чітко.
Джо Кінгтон

2
Якщо у когось є проблеми, використовуйтеfig = plt.gcf()
KyungHoon Kim

148

Ви можете налаштувати інтервал навколо фігур matplotlib за допомогою функції subplots_adjust ():

import matplotlib.pyplot as plt
plt.plot(whatever)
plt.subplots_adjust(left=0.1, right=0.9, top=0.9, bottom=0.1)

Це буде працювати як для малюнка на екрані, так і для збереження у файл, і це правильна функція для виклику, навіть якщо на одній фігурі у вас немає декількох графіків.

Цифри є дробами розмірів фігури, і їх потрібно буде відкоригувати, щоб враховувати позначення фігур.


8
Значення, присвоєні параметрам, а не скільки їх змінити, вони є де встановити поле. Іншими словами, якщо ви хочете довести правильну межу поля на 10%, вам слід встановити правильний = 0,9, а не правильний = 0,1 matplotlib.sourceforge.net/api/…
drootang

1
Є сенс зазначити, що, очевидно, ви можете вказати негативні значення в plt.subplots_adjust (). Це навіть дозволяє малювати поза площею фігури, а також боротися з дратівливими полями.
сюрч

Це також працює над GridSpecоб'єктами, викликаючи updateметод (див. Stackoverflow.com/a/20058199/1030876 ).
Аарон Фолкер

57

Все, що тобі потрібно, це

plt.tight_layout()

перед вашим результатом.

Окрім зменшення поля, це також щільно групує простір між будь-якими підсплавами:

x = [1,2,3]
y = [1,4,9]
import matplotlib.pyplot as plt
fig = plt.figure()
subplot1 = fig.add_subplot(121)
subplot1.plot(x,y)
subplot2 = fig.add_subplot(122)
subplot2.plot(y,x)
fig.tight_layout()
plt.show()

7
Я думаю, що це дійсно найкращий метод. Для цього не потрібно зберігати фігуру на зразок `bbox = 'close' і виправляє всі види інших макетів у тісних фігурах.
дшеферд

2
це має бути правильна відповідь, оскільки він поводиться так, як ви очікували, оскільки це стосується зображення, а не зображення.
Маджід альДосарі

Як не дивно, це також змінює ширину фактичної ділянки (тобто вершини розташовані ближче один до одного) порівняно з bbox_inches='tight', що просто обрізає пробіл навколо країв, але залишає ділянку в спокої. Я створив фігуру с plt.figure(figsize=(10,3)).
Фріц

9

Просто використовуйте, ax = fig.add_axes([left, bottom, width, height]) якщо ви хочете точно контролювати макет фігури. напр.

left = 0.05
bottom = 0.05
width = 0.9
height = 0.9
ax = fig.add_axes([left, bottom, width, height])

6

Якщо хтось задається питанням, як позбутися залишків білого поля після застосування plt.tight_layout()або fig.tight_layout(): За допомогою параметра pad(який 1.08за замовчуванням) ви можете зробити його ще більш жорстким: "Прокладка між краєм фігури та краями субплоти, як частка від розміру шрифту. " Так, наприклад

plt.tight_layout(pad=0.05)

зменшить його до дуже невеликого запасу. Поміщення 0не працює для мене, оскільки це також робить коробку субплота трохи відрізаною.


4
plt.savefig("circle.png", bbox_inches='tight',pad_inches=-1)

1
"pad_inches = -1", тому що моя збережена цифра створює лише частину фігури.
Ю. Шень

Використовувати параметр у savefigфункції є елегантним, проте негативне значення pad_inchesне обов’язково потрібне в кожному випадку.
MichaelHuelsen

встановити його на 0, допомагає
Joop

4

Проблема з matplotlibs subplots_adjust полягає в тому, що введені значення відносно значень x і y фігури. Цей приклад для правильної цифри для друку PDF-файлу:

Для цього я перераховую відносний інтервал до абсолютних значень, як це:

pyplot.subplots_adjust(left = (5/25.4)/figure.xsize, bottom = (4/25.4)/figure.ysize, right = 1 - (1/25.4)/figure.xsize, top = 1 - (3/25.4)/figure.ysize)

для фігури "figure.xsize" дюймів у x-вимірі та "figure.ysize" дюймів у y-вимірі. Таким чином, вся малюнок має лівий запас 5 мм, нижній край 4 мм, правий 1 мм і верхній на 3 мм. Перетворення (x / 25.4) проводиться тому, що мені потрібно було перетворити мм на дюйми.

Зауважте, що чистий розмір діаграми x буде "figure.xsize - лівий запас - правий край", а чистий розмір діаграми y буде "figure.ysize - нижня межа - верхня межа" в дюймах

Інші фрагменти (не впевнений у цих, я просто хотів надати інші параметри)

pyplot.figure(figsize = figureSize, dpi = None)

і

pyplot.savefig("outputname.eps", dpi = 100)

3
Звідки ти взяв xsizeі ysizeзвідки. Я використовую ці властивості, і отримуюAttributeError: 'Figure' object has no attribute 'xsize'
cj5

4

натхненний відповіддю Самміса вище:

margins = {  #     vvv margin in inches
    "left"   :     1.5 / figsize[0],
    "bottom" :     0.8 / figsize[1],
    "right"  : 1 - 0.3 / figsize[0],
    "top"    : 1 - 1   / figsize[1]
}
fig.subplots_adjust(**margins)

Де figsize - це кортеж, який ви використовували fig = pyplot.figure(figsize=...)


2

Для мене відповіді вище не працювали matplotlib.__version__ = 1.4.3на Win7. Отже, якщо нас цікавить лише саме зображення (тобто, якщо нам не потрібні анотації, вісь, галочки, заголовок, ylabel тощо), тоді краще просто зберегти numpy масив як зображення savefig.

from pylab import *

ax = subplot(111)
ax.imshow(some_image_numpyarray)
imsave('test.tif', some_image_numpyarray)

# or, if the image came from tiff or png etc
RGBbuffer = ax.get_images()[0].get_array()
imsave('test.tif', RGBbuffer)

Також, використовуючи функції малювання opencv (cv2.line, cv2.polylines), ми можемо зробити кілька малюнків безпосередньо на масиві numpy. http://docs.opencv.org/2.4/modules/core/doc/drawing_functions.html


Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.