Получение одинакового размера подзадачи с использованием matplotlib imshow и разброса
Я пытаюсь построить изображение (используя matplotlib.imshow
) и график рассеяния на одном и том же рисунке. При попытке этого изображения изображение оказывается меньше, чем график рассеяния. Ниже показан небольшой пример кода:
import matplotlib.pyplot as plt
import numpy as np
image = np.random.randint(100,200,(200,200))
x = np.arange(0,10,0.1)
y = np.sin(x)
fig, (ax1, ax2) = plt.subplots(1,2)
ax1.imshow(image)
ax2.scatter(x,y)
plt.show()
Что дает следующий рисунок:
![введите описание изображения здесь]()
Как я могу получить две подсловы одинаковой высоты? (и, по-видимому, ширина)
Я попытался использовать gridspec
, как показано в this:
fig=plt.figure()
gs=GridSpec(1,2)
ax1=fig.add_subplot(gs[0,0])
ax2=fig.add_subplot(gs[0,1])
ax1.imshow(image)
ax2.scatter(x,y)
Но это дает тот же результат. Я также попытался настроить размеры подзаголовков вручную, используя:
fig = plt.figure()
ax1 = plt.axes([0.05,0.05,0.45,0.9])
ax2 = plt.axes([0.55,0.19,0.45,0.62])
ax1.imshow(image)
ax2.scatter(x,y)
В результате проб и ошибок я могу получить два подзаголовка до нужного размера, хотя любое изменение общего размера фигуры будет означать, что подзаголовки больше не будут иметь одинаковый размер.
Есть ли способ сделать график imshow
и scatter
таким же размером на фигуре без изменения размеров осей вручную?
Я использую Python 2.7 и matplotlib 2.0.0
Ответы
Ответ 1
Не совсем понятно, какой у вас желаемый результат.
Вы можете использовать автоматический аспект на изображении
ax.imshow(z, aspect="auto")
![enter image description here]()
Или вы можете установить аспект линейного графика в зависимости от пределов его оси так, чтобы он получал тот же размер, что и изображение (в случае, если изображение имеет равные размеры x и y)
asp = np.diff(ax2.get_xlim())[0] / np.diff(ax2.get_ylim())[0]
ax2.set_aspect(asp)
Полный код:
import numpy as np
import matplotlib.pyplot as plt
x = np.linspace(0,10,20)
y = np.sin(x)
z = np.random.rand(100,100)
fig, (ax, ax2) = plt.subplots(ncols=2)
ax.imshow(z)
ax2.plot(x,y, marker=".")
asp = np.diff(ax2.get_xlim())[0] / np.diff(ax2.get_ylim())[0]
ax2.set_aspect(asp)
plt.show()
Если изображение не имеет равных пределов (не является квадратным), его все равно необходимо разделить на аспект изображения:
asp = np.diff(ax2.get_xlim())[0] / np.diff(ax2.get_ylim())[0]
asp /= np.abs(np.diff(ax1.get_xlim())[0] / np.diff(ax1.get_ylim())[0])
ax2.set_aspect(asp)
Более сложные решения:
Этот ответ для использования параметров подзаговора для достижения определенного аспекта.
Если вы хотите использовать mpl_toolkits
и испачкать руки, этот ответ будет хорошим чтением.
Ответ 2
У меня была такая же проблема, и я задал очень похожий вопрос в SO. Решение, предложенное @ImportanceOfBeingErnest, работало как прелесть для меня, но для полноты я хотел бы упомянуть довольно простой обходной путь, который мне предлагали применить (кредит для @Yilun Zhang), прежде чем мой вопрос был отмечен как точный дубликат этого один:
Проблема заключается в том, что высота области графика слишком велика, и это оставляет пустое место на изображении.
Если вы измените свой код на:
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(14, 6))
тогда вы получите желаемый результат:
![Желаемый результат]()
Ответ 3
Вот код, который я использую:
fig, axis_array = plt.subplots(1, 2, figsize=(chosen_value, 1.05 * chosen_value / 2),
subplot_kw={'aspect': 1})
Я явно выбираю, что на моей фигуре будет 2 подзаголовка, и что эта цифра будет выбрана равной значению, а каждая подзадача будет примерно вдвое меньше, чем ширина, и что подзаголовки будут иметь соотношение сторон 1 ( т.е. они будут квадратными). Размер фигуры - это конкретное соотношение, которое заставляет интервал.