W3docs

Точечные диаграммы Matplotlib в Python — полное руководство

Создание и настройка точечных диаграмм в Python с Matplotlib: цвет, размер, прозрачность, цветовая шкала, несколько групп и аннотации.

Функция scatter() в Matplotlib позволяет визуализировать зависимость между двумя числовыми переменными, размещая маркер в каждой точке (x, y). В отличие от линейного графика, точечные диаграммы не предполагают ни порядка, ни непрерывности — каждая точка самостоятельна. Это делает их основным инструментом для изучения корреляций, поиска кластеров и обнаружения выбросов.

В этой главе рассматривается всё — от первой точечной диаграммы до профессиональных техник: кодирование цвета и размера каждой точки, прозрачность, цветовые шкалы, многогрупповые графики, аннотации точек и сохранение файлов, готовых к публикации.

Перед началом убедитесь, что Matplotlib установлен:

pip install matplotlib

Если вы только знакомитесь с Matplotlib, сначала прочитайте главы Введение в Matplotlib и Начало работы.

Когда использовать точечную диаграмму

Используйте точечную диаграмму, когда:

  • Вы хотите изучить корреляцию между двумя числовыми переменными (рост и вес, часы учёбы и оценка на экзамене).
  • Вам нужно обнаружить кластеры — группы точек, которые естественно сближаются.
  • Вы хотите выявить выбросы — точки, далеко отстоящие от основного распределения.
  • Вы кодируете третью переменную через размер или цвет маркера («пузырьковая диаграмма» — это точечная диаграмма, где размер = третья переменная).

Избегайте точечных диаграмм, когда одна ось представляет неупорядоченные категории — там нагляднее столбчатая диаграмма. Для отображения трендов по непрерывной упорядоченной переменной лучше подходит линейный график.

Создание базовой точечной диаграммы

Передайте в plt.scatter() две последовательности одинаковой длины — значения x и значения y:

import matplotlib.pyplot as plt

x = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
y = [2, 4, 5, 4, 7, 8, 6, 9, 10, 12]

plt.scatter(x, y)

plt.title('Basic Scatter Plot')
plt.xlabel('X Values')
plt.ylabel('Y Values')

plt.tight_layout()
plt.show()

plt.tight_layout() предотвращает обрезку подписей — сделайте это привычкой перед каждым вызовом show() или savefig().

Настройка размера маркеров

Параметр s управляет размером маркера в квадратных пунктах (по умолчанию 20). Увеличьте его, чтобы точки были лучше видны, особенно в презентациях:

import matplotlib.pyplot as plt

x = [1, 2, 3, 4, 5, 6, 7, 8]
y = [3, 1, 4, 1, 5, 9, 2, 6]

plt.scatter(x, y, s=120)

plt.title('Larger Markers')
plt.xlabel('X')
plt.ylabel('Y')
plt.tight_layout()
plt.show()

В s можно передать список или array, чтобы каждая точка имела собственный размер — именно так кодируется третья числовая переменная в виде площади пузырька:

import matplotlib.pyplot as plt

x      = [1, 2, 3, 4, 5]
y      = [5, 3, 6, 2, 7]
sizes  = [100, 300, 50, 400, 200]   # third variable encoded as bubble area

plt.scatter(x, y, s=sizes)

plt.title('Bubble Chart — size encodes a third variable')
plt.xlabel('X')
plt.ylabel('Y')
plt.tight_layout()
plt.show()

Настройка цвета маркеров

Один цвет для всех точек

Передайте имя цвета, hex-строку или RGB-кортеж в c (или color):

import matplotlib.pyplot as plt

x = [1, 2, 3, 4, 5]
y = [2, 4, 1, 5, 3]

plt.scatter(x, y, s=100, c='steelblue')

plt.title('Single Color')
plt.xlabel('X')
plt.ylabel('Y')
plt.tight_layout()
plt.show()

Цвет каждой точки из числовой переменной

Передача array в c отображает каждое значение на цвет через цветовую карту, указанную в cmap. Добавьте plt.colorbar(), чтобы показать, что означают цвета:

import matplotlib.pyplot as plt
import numpy as np

rng = np.random.default_rng(seed=42)
x      = rng.random(50)
y      = rng.random(50)
values = rng.random(50)          # third variable, e.g. intensity or temperature

scatter = plt.scatter(x, y, s=80, c=values, cmap='viridis')
plt.colorbar(scatter, label='Intensity')

plt.title('Color-Mapped Scatter Plot')
plt.xlabel('X')
plt.ylabel('Y')
plt.tight_layout()
plt.show()

'viridis' — перцептивно равномерная цветовая карта, читаемая в оттенках серого и доступная для людей с нарушением цветового восприятия. Другие хорошие варианты: 'plasma', 'cividis' и 'coolwarm'.

Управление прозрачностью с помощью alpha

Когда много точек перекрываются, они образуют непрозрачное пятно, скрывающее реальную плотность. Задайте alpha (0 = полностью прозрачный, 1 = полностью непрозрачный), чтобы обнажить структуру перекрытий:

import matplotlib.pyplot as plt
import numpy as np

rng = np.random.default_rng(seed=0)
x = rng.normal(loc=0, scale=1, size=300)
y = rng.normal(loc=0, scale=1, size=300)

plt.scatter(x, y, s=40, alpha=0.4)

plt.title('Transparent Markers Reveal Density (alpha=0.4)')
plt.xlabel('X')
plt.ylabel('Y')
plt.tight_layout()
plt.show()

Хорошей отправной точкой является alpha=0.4 до 0.6. Подбирайте значение в зависимости от количества точек.

Стилизация границ маркеров

Используйте edgecolors, чтобы добавить рамку вокруг каждого маркера, и linewidths, чтобы управлять её толщиной. Это помогает точкам выделяться на цветном фоне:

import matplotlib.pyplot as plt

x = [1, 2, 3, 4, 5, 6]
y = [3, 1, 4, 1, 5, 9]

plt.scatter(x, y, s=150, c='gold', edgecolors='black', linewidths=1.5)

plt.title('Markers with Edges')
plt.xlabel('X')
plt.ylabel('Y')
plt.tight_layout()
plt.show()

Передайте edgecolors='none', чтобы полностью убрать рамки (это значение по умолчанию для большинства цветовых карт).

Отображение нескольких групп

Для сравнения групп вызывайте plt.scatter() по одному разу для каждой группы и задавайте метку. Matplotlib автоматически присваивает разный цвет каждому вызову:

import matplotlib.pyplot as plt
import numpy as np

rng = np.random.default_rng(seed=7)

# Group A — centered around (2, 3)
ax_x = rng.normal(loc=2, scale=0.5, size=30)
ax_y = rng.normal(loc=3, scale=0.5, size=30)

# Group B — centered around (5, 6)
bx_x = rng.normal(loc=5, scale=0.5, size=30)
bx_y = rng.normal(loc=6, scale=0.5, size=30)

# Group C — centered around (8, 2)
cx_x = rng.normal(loc=8, scale=0.5, size=30)
cx_y = rng.normal(loc=2, scale=0.5, size=30)

plt.scatter(ax_x, ax_y, s=60, label='Group A')
plt.scatter(bx_x, bx_y, s=60, label='Group B')
plt.scatter(cx_x, cx_y, s=60, label='Group C')

plt.legend()
plt.title('Multi-Group Scatter Plot')
plt.xlabel('X')
plt.ylabel('Y')
plt.tight_layout()
plt.show()

Каждый вызов scatter() автоматически берёт следующий цвет из стандартного цикла. Передайте c='red' (или любой цвет), чтобы переопределить его.

Аннотирование отдельных точек

Используйте plt.annotate() для подписи конкретных точек — это удобно для выделения выбросов или ключевых наблюдений:

import matplotlib.pyplot as plt

cities = ['London', 'Berlin', 'Madrid', 'Rome', 'Paris']
population = [9.0, 3.7, 3.3, 2.8, 2.1]   # millions
area       = [1572, 892, 604, 1285, 105]   # km²

plt.scatter(area, population, s=100, c='steelblue', edgecolors='black', linewidths=0.8)

for i, city in enumerate(cities):
    plt.annotate(
        city,
        xy=(area[i], population[i]),
        xytext=(8, 4),                      # offset in points
        textcoords='offset points',
        fontsize=9,
    )

plt.title('European City Population vs. Area')
plt.xlabel('Area (km²)')
plt.ylabel('Population (millions)')
plt.tight_layout()
plt.show()

Паттерн xytext + textcoords='offset points' немного смещает подпись, чтобы она не накладывалась непосредственно на маркер.

Использование логарифмических осей

Когда данные охватывают несколько порядков величины, линейные оси сжимают большинство точек в один угол. Переключитесь на логарифмический масштаб с помощью plt.xscale('log') или plt.yscale('log'):

import matplotlib.pyplot as plt
import numpy as np

rng = np.random.default_rng(seed=1)
x = np.logspace(1, 5, 60)            # 10¹ to 10⁵
y = x * rng.uniform(0.5, 2.0, 60)   # roughly proportional, with noise

plt.scatter(x, y, s=40, alpha=0.7)
plt.xscale('log')
plt.yscale('log')

plt.title('Log-Scale Scatter Plot')
plt.xlabel('X (log scale)')
plt.ylabel('Y (log scale)')
plt.tight_layout()
plt.show()

Обе оси теперь охватывают равные интервалы степеней десяти, равномерно распределяя данные по области графика.

Добавление линии регрессии

Точечная диаграмма показывает отдельные точки; добавление линии наилучшего соответствия демонстрирует общий тренд. Вычислите наклон и сдвиг с помощью np.polyfit():

import matplotlib.pyplot as plt
import numpy as np

rng = np.random.default_rng(seed=3)
x = np.linspace(0, 10, 40)
y = 2.5 * x + rng.normal(scale=3, size=40)   # linear trend + noise

# Fit a degree-1 polynomial (straight line)
slope, intercept = np.polyfit(x, y, 1)
trend_line = slope * x + intercept

plt.scatter(x, y, s=50, label='Data points', alpha=0.7)
plt.plot(x, trend_line, color='red', linewidth=2, label=f'Trend (slope={slope:.2f})')

plt.legend()
plt.title('Scatter Plot with Regression Line')
plt.xlabel('X')
plt.ylabel('Y')
plt.tight_layout()
plt.show()

np.polyfit(x, y, 1) возвращает [slope, intercept] для линии наилучшего соответствия, проходящей через точки.

Сохранение точечной диаграммы в файл

Используйте plt.savefig() вместо plt.show(), чтобы записать диаграмму на диск. Вызывайте его до plt.show() — после show() фигура очищается:

import matplotlib.pyplot as plt
import numpy as np

rng = np.random.default_rng(seed=9)
x = rng.random(60)
y = rng.random(60)

plt.scatter(x, y, s=60, alpha=0.6, c='teal', edgecolors='white', linewidths=0.5)
plt.title('Saved Scatter Plot')
plt.xlabel('X')
plt.ylabel('Y')
plt.tight_layout()

plt.savefig('scatter.png', dpi=150)   # PNG at 150 DPI
plt.savefig('scatter.pdf')             # vector PDF — best for publication
plt.show()

Распространённые форматы: 'png' (растр, веб), 'pdf' (вектор, публикация), 'svg' (вектор, веб). Увеличьте dpi до 300 для растров печатного качества.

scatter() vs plot() — что выбрать?

Обе функции могут строить графики только из маркеров, но служат разным целям:

Возможностьplt.scatter()plt.plot()
Размер каждой точки (s)Да — передайте arrayНет
Цвет каждой точки (c)Да — передайте arrayНет (один цвет на вызов)
Поддержка цветовой картыДа (cmap)Ограниченная
Производительность на больших наборах данныхМедленнееБыстрее
Соединяющая линияНетДа

Используйте scatter(), когда нужна индивидуальная стилизация точек (цвет или размер зависят от данных). Используйте plot(marker='o', linestyle='None') для простых графиков на больших наборах данных, где важна скорость. Подробнее о стилях маркеров — в главе Маркеры Matplotlib.

Полный пример

Следующий самодостаточный скрипт объединяет наиболее полезные техники — отображение цвета, кодирование размера, прозрачность, цветовую шкалу и легенду:

import matplotlib.pyplot as plt
import numpy as np

rng = np.random.default_rng(seed=42)

n = 80
x      = rng.standard_normal(n)
y      = 0.8 * x + rng.standard_normal(n) * 0.6   # correlated
sizes  = rng.uniform(30, 200, n)                   # bubble area
values = rng.random(n)                             # third variable for color

fig, ax = plt.subplots(figsize=(8, 5))

sc = ax.scatter(
    x, y,
    s=sizes,
    c=values,
    cmap='plasma',
    alpha=0.75,
    edgecolors='white',
    linewidths=0.5,
)

plt.colorbar(sc, ax=ax, label='Intensity')

ax.set_title('Comprehensive Scatter Plot Example', fontsize=13)
ax.set_xlabel('X Variable')
ax.set_ylabel('Y Variable (correlated)')
fig.tight_layout()
plt.savefig('scatter_complete.png', dpi=150)
plt.show()

Ключевые моменты:

  • fig, ax = plt.subplots() даёт вам явные объекты фигуры и осей — рекомендуемый подход для всего, что выходит за рамки быстрого прототипа.
  • ax.scatter() для объекта Axes ведёт себя идентично plt.scatter().
  • plt.colorbar(sc, ax=ax, label='...') прикрепляет цветовую шкалу к конкретным осям.

Лучшие практики

  • Показывайте шкалу. Если используете c с цветовой картой, всегда добавляйте цветовую шкалу, чтобы читатели понимали, что означают цвета.
  • Избегайте наложения точек. При более чем ~500 точках задайте alpha < 1 или перейдите к 2D-гистограмме (plt.hist2d()) или шестиугольной диаграмме (plt.hexbin()).
  • Выбирайте доступные цветовые карты. 'viridis', 'plasma' и 'cividis' — перцептивно равномерные и дружественные к людям с нарушением цветового восприятия. Избегайте 'jet' и 'rainbow'.
  • Подписывайте оси с единицами. plt.xlabel('Height (cm)') информативнее, чем plt.xlabel('Height').
  • Добавляйте заголовок, отражающий вывод. «Рост vs. Вес — положительная корреляция» полезнее, чем «Точечная диаграмма».

Связанные главы

Was this page helpful?