2025, Nov 16 12:01
Увеличиваем маркер scatter и шрифт легенды в Matplotlib
Разберемся, почему маркер scatter в легенде Matplotlib остается маленьким, и как увеличить его: через markerscale при legend() или set_sizes у PathCollection.
При подготовке фигур Matplotlib к экспорту увеличить кегль текста в легенде несложно, но значок scatter в легенде часто остается крошечным. Обычные правки, затрагивающие только шрифт, не меняют сам маркер, из‑за чего аккуратно выверенная фигура выглядит несогласованной. Ниже показано, как корректно масштабировать и текст легенды, и маркер scatter.
Воспроизводим проблему
Задумка — укрупнить текст легенды, но точка рядом с подписью остается маленькой:
import matplotlib.pyplot as plt
def grow_legend(ax_obj, text_size=25):
for t in ax_obj.get_legend().get_texts():
t.set_fontsize(text_size)
fig, axe = plt.subplots()
axe.scatter([1, 2, 3], [2, 3, 1], label="auto")
axe.legend()
grow_legend(axe)
Кегль действительно увеличивается, но размер маркера в легенде не меняется.
Что на самом деле происходит
Символ, который попадает в легенду для scatter-графика, — это PathCollection, а не Line2D или Patch. Поэтому get_patches и get_lines для этой легенды возвращают пустые последовательности. Видимый маркер — не линия и не патч; это handle коллекции scatter. Чтобы масштабировать этот символ, либо задайте markerscale при создании легенды, либо измените sizes у коллекции после создания легенды.
Два практических способа решения
Самый прямой подход — управлять символом при создании легенды через markerscale. Он масштабирует маркер легенды относительно размера маркера на графике и логично сочетается с fontsize:
import matplotlib.pyplot as plt
fig, axis = plt.subplots()
axis.scatter([1, 2, 3], [2, 3, 1], label='auto')
# Масштабируем и текст, и точку легенды
axis.legend(fontsize=25, markerscale=3)
Если удобнее воспользоваться вспомогательной функцией для уже существующей легенды, можно изменить и текст, и размеры handle scatter. Главное — получить handles легенды и вызвать set_sizes, передав площадь в пунктах²:
import matplotlib.pyplot as plt
def resize_legend(axi, txt_size=25, dot_area=200):
leg = axi.get_legend()
for item in leg.get_texts():
item.set_fontsize(txt_size)
# Учтите различия в названиях атрибутов между версиями Matplotlib
handles = getattr(leg, "legendHandles", getattr(leg, "legend_handles", []))
for h in handles:
h.set_sizes([dot_area])
fig, axis = plt.subplots()
axis.scatter([1, 2, 3], [2, 3, 1], label='auto')
axis.legend()
resize_legend(axis)
Оба подхода увеличивают маркер в легенде под визуальный «вес» текста, делая легенду готовой к экспорту.
Почему это важно
Легенды — часть визуальной иерархии фигуры. Когда шрифт становится крупнее, а символы остаются мелкими, баланс нарушается, и просматривать такую легенду сложнее. Совместное масштабирование маркеров и подписей сохраняет целостность рисунка и повышает читаемость в отчетах и публикациях.
Рекомендации
Используйте markerscale, если при создании легенды вы заранее знаете целевой размер. Если нужно доработать уже построенные графики или требуется явный контроль площади маркера в пунктах², получите handles легенды и вызовите set_sizes у PathCollection. В средах с разными версиями Matplotlib обращайтесь к handles «защитно», как показано выше, чтобы избежать ошибок атрибутов.
Согласованность текста и маркеров в легенде — небольшая доработка с большим эффектом для ясности и качества подачи.