Круговые диаграммы в Matplotlib
Создавайте и настраивайте круговые диаграммы в Python с Matplotlib: цвета, explode, donut-диаграммы, подписи, легенды и сохранение в файл.
Круговые диаграммы делят окружность на секторы, где угол каждого сектора пропорционален представляемому значению. Они лучше всего подходят, когда категорий немного (в идеале 2–6) и нужно показать, как каждая часть соотносится с целым — например, доля рынка по продуктам или распределение бюджета по отделам.
В этой главе рассматривается всё: от минимального первого графика до продвинутых техник, таких как donut-диаграммы, произвольное размещение подписей и сохранение готовых к публикации изображений. Во всех примерах используется matplotlib.pyplot — стандартный высокоуровневый API.
Установка и настройка
Если Matplotlib ещё не установлен, выполните эту команду в терминале:
pip install matplotlibКаждый пример в этой главе начинается со следующего импорта:
import matplotlib.pyplot as pltplt — стандартный псевдоним для matplotlib.pyplot. Он предоставляет такие функции, как plt.pie(), plt.title() и plt.show().
Создание базовой круговой диаграммы
plt.pie() — основная функция. Минимально она принимает последовательность числовых значений — пропорции вычисляются автоматически.
import matplotlib.pyplot as plt
labels = ['Desktop', 'Mobile', 'Tablet']
values = [60, 30, 10]
plt.pie(values, labels=labels, autopct='%1.1f%%')
plt.title('Website Visitors by Device')
plt.show()Ключевые используемые параметры:
| Параметр | Назначение |
|---|---|
values | Числовые данные; Matplotlib преобразует их в пропорции |
labels | Названия категорий, отображаемые рядом с каждым сектором |
autopct | Строка форматирования для подписей процентов; '%1.1f%%' даёт 60.0% |
По умолчанию диаграмма начинает рисовать секторы против часовой стрелки от позиции «3 часа». В следующем разделе объясняется, как это изменить.
Управление поворотом с помощью startangle
Установка startangle=90 поворачивает всю диаграмму так, что первый сектор начинается в позиции «12 часов» — наиболее естественная отправная точка для большинства читателей.
import matplotlib.pyplot as plt
labels = ['Desktop', 'Mobile', 'Tablet']
values = [60, 30, 10]
plt.pie(
values,
labels=labels,
autopct='%1.1f%%',
startangle=90,
)
plt.title('Website Visitors by Device')
plt.show()startangle принимает любой угол в градусах, отсчитываемый против часовой стрелки от положительной оси x. Значение 90 указывает прямо вверх.
Настройка цветов
Передайте список цветовых кодов в формате hex или именованных цветов в параметр colors. Список должен быть не короче, чем ваши данные.
import matplotlib.pyplot as plt
labels = ['Desktop', 'Mobile', 'Tablet']
values = [60, 30, 10]
colors = ['#ff9999', '#66b3ff', '#99ff99']
plt.pie(
values,
labels=labels,
colors=colors,
autopct='%1.1f%%',
startangle=90,
)
plt.title('Website Visitors by Device')
plt.show()Также можно использовать любые встроенные цветовые карты Matplotlib. Например, чтобы получить три цвета из палитры tab10:
import matplotlib.pyplot as plt
import matplotlib.cm as cm
labels = ['Desktop', 'Mobile', 'Tablet']
values = [60, 30, 10]
cmap = cm.get_cmap('tab10')
colors = [cmap(i) for i in range(len(values))]
plt.pie(values, labels=labels, colors=colors, autopct='%1.1f%%', startangle=90)
plt.title('Website Visitors by Device')
plt.show()Выдвижение сектора
Параметр explode смещает один или несколько секторов наружу, привлекая к ним внимание. Он принимает кортеж значений с плавающей точкой — по одному на каждый сектор. Значение 0.1 смещает сектор на 10 % радиуса диаграммы.
import matplotlib.pyplot as plt
labels = ['Desktop', 'Mobile', 'Tablet']
values = [60, 30, 10]
colors = ['#ff9999', '#66b3ff', '#99ff99']
explode = (0.1, 0, 0) # offset the first slice (Desktop) only
plt.pie(
values,
labels=labels,
colors=colors,
explode=explode,
autopct='%1.1f%%',
startangle=90,
shadow=True, # drop shadow for depth
)
plt.title('Website Visitors by Device')
plt.show()Установка shadow=True добавляет едва заметную тень, которая ещё больше акцентирует внимание на выдвинутом секторе.
Добавление заголовка и легенды
Используйте plt.title() для заголовка диаграммы и plt.legend() для отдельного блока легенды. Легенда полезна, когда текст подписей длинный или секторы слишком маленькие, чтобы подписать их напрямую.
import matplotlib.pyplot as plt
labels = ['Desktop', 'Mobile', 'Tablet']
values = [60, 30, 10]
colors = ['#ff9999', '#66b3ff', '#99ff99']
plt.pie(
values,
labels=labels,
colors=colors,
autopct='%1.1f%%',
startangle=90,
)
plt.title('Website Visitors by Device')
plt.legend(title='Device type', loc='lower right')
plt.show()loc принимает стандартные строки позиционирования, такие как 'upper right', 'lower left' и 'center'. Также можно передать кортеж bbox_to_anchor для точного позиционирования в пикселях.
Управление расстоянием подписей
Два параметра определяют, как далеко подписи расположены от центра диаграммы:
labeldistance— расстояние подписи категории от центра, выраженное как доля радиуса. По умолчанию1.1(немного снаружи сектора).pctdistance— расстояние подписи процента autopct от центра. По умолчанию0.6(внутри сектора).
import matplotlib.pyplot as plt
labels = ['Desktop', 'Mobile', 'Tablet']
values = [60, 30, 10]
plt.pie(
values,
labels=labels,
autopct='%1.1f%%',
startangle=90,
labeldistance=1.2, # push category labels further out
pctdistance=0.75, # move percentages slightly outward from center
)
plt.title('Website Visitors by Device')
plt.show()Увеличивайте pctdistance, когда секторы крупные и расположение по умолчанию выглядит загромождённым; уменьшайте, когда много маленьких секторов.
Создание donut-диаграммы
Donut-диаграмма — это круговая диаграмма с отверстием посередине. Используйте параметр wedgeprops, чтобы задать ширину кольца, выраженную как доля радиуса. Например, width=0.5 оставляет 50 % радиуса в качестве отверстия.
import matplotlib.pyplot as plt
labels = ['Desktop', 'Mobile', 'Tablet']
values = [60, 30, 10]
colors = ['#ff9999', '#66b3ff', '#99ff99']
plt.pie(
values,
labels=labels,
colors=colors,
autopct='%1.1f%%',
startangle=90,
pctdistance=0.85,
wedgeprops=dict(width=0.5), # ring width = 50 % of radius
)
plt.title('Website Visitors by Device')
plt.show()Donut-диаграммы популярны, поскольку пустой центр предоставляет место для общего числа или сводной метрики, которую можно добавить с помощью plt.text(0, 0, 'Total\n100', ha='center', va='center', fontsize=14).
Несколько круговых диаграмм рядом
Используйте plt.subplots(), чтобы разместить две или более круговых диаграммы на одном рисунке. Каждый вызов ax.pie() направлен на собственный объект осей.
import matplotlib.pyplot as plt
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(10, 5))
# --- Chart 1: this month ---
labels = ['Desktop', 'Mobile', 'Tablet']
values_this_month = [60, 30, 10]
ax1.pie(values_this_month, labels=labels, autopct='%1.1f%%', startangle=90)
ax1.set_title('This Month')
# --- Chart 2: last month ---
values_last_month = [70, 20, 10]
ax2.pie(values_last_month, labels=labels, autopct='%1.1f%%', startangle=90)
ax2.set_title('Last Month')
fig.suptitle('Website Visitors by Device', fontsize=14)
plt.tight_layout()
plt.show()fig.suptitle() добавляет заголовок над всеми подграфиками. plt.tight_layout() предотвращает наложение подписей между диаграммами.
Сохранение круговой диаграммы в файл
Замените plt.show() на plt.savefig(), чтобы записать диаграмму на диск вместо отображения в окне. Это необходимо для скриптов, выполняемых на серверах без графического интерфейса, или для создания отчётных изображений.
import matplotlib.pyplot as plt
labels = ['Desktop', 'Mobile', 'Tablet']
values = [60, 30, 10]
plt.pie(values, labels=labels, autopct='%1.1f%%', startangle=90)
plt.title('Website Visitors by Device')
plt.savefig('pie_chart.png', dpi=150, bbox_inches='tight')Распространённые параметры savefig():
| Параметр | Эффект |
|---|---|
dpi=150 | Разрешение в точках на дюйм (72–300 для типичного использования) |
bbox_inches='tight' | Обрезает пустые поля вокруг рисунка |
transparent=True | Сохраняет с прозрачным фоном |
format='svg' | Создаёт векторный SVG вместо растрового PNG |
Распространённые ошибки
Значения, которые не составляют 100 в сумме. plt.pie() всегда нормализует значения так, чтобы секторы заполняли полную окружность. Если ваши значения представляют проценты и уже в сумме дают 100 — всё нормально. Если они представляют абсолютные числа — тоже нормально: Matplotlib делит каждое значение на общую сумму. Подпись autopct всегда показывает долю, а не исходное значение.
Нулевые или отрицательные значения. Matplotlib молча пропускает секторы с нулевым значением (они не создают видимого сектора). Отрицательные значения вызывают ValueError. Отфильтруйте их перед вызовом plt.pie().
Слишком много секторов. Круговые диаграммы становятся нечитаемыми при более чем 6–8 секторах. При большом числе категорий рассмотрите столбчатую диаграмму. Как вариант, объедините наименьшие категории в один сектор «Прочее».
Наложение подписей. Когда секторы маленькие, подписи перекрываются. Решения: увеличить labeldistance, использовать легенду вместо встроенных подписей (установите labels=None и вызовите plt.legend()), или использовать donut-диаграмму с бо́льшим пространством снаружи.
Краткий справочник
| Параметр | Тип | По умолчанию | Назначение |
|---|---|---|---|
x | sequence | — | Значения данных |
labels | list | None | Названия категорий |
colors | list | cycle | Цвета секторов |
explode | tuple | None | Смещение каждого сектора от центра |
autopct | str / callable | None | Формат подписей процентов |
pctdistance | float | 0.6 | Расстояние подписи процента от центра |
labeldistance | float | 1.1 | Расстояние подписи категории от центра |
startangle | float | 0 | Начальный угол в градусах |
shadow | bool | False | Тень |
wedgeprops | dict | None | Свойства каждого сегмента (например, width для donut) |
counterclock | bool | True | Направление отрисовки секторов |
Связанные темы
- Столбчатые диаграммы Matplotlib — предпочтительнее круговых диаграмм, когда категорий много или нужны точные сравнения.
- Гистограммы Matplotlib — для визуализации распределения непрерывных данных.
- Подписи Matplotlib — как добавлять и оформлять подписи осей, заголовки и аннотации.
- Подграфики Matplotlib — размещение нескольких диаграмм на одном рисунке.