Имеется ли функция matplotlib для рисования диагональных линий в координатах оси?
Оси Matplotlib имеют функции axhline
и axvline
для рисования горизонтальных или вертикальных линий при заданной координате y или x (соответственно) независимо от шкалы данных осей.
Есть ли аналогичная функция для построения постоянной диагонали? Например, если у меня есть диаграмма рассеяния переменных с подобным доменом, часто бывает полезно знать, попадают ли они выше или ниже строки y = x
:
mean, cov = [0, 0], [(1, .6), (.6, 1)]
x, y = np.random.multivariate_normal(mean, cov, 100).T
y += x + 1
f, ax = plt.subplots(figsize=(6, 6))
ax.scatter(x, y, c=".3")
ax.plot([-3, 3], [-3, 3], ls="--", c=".3")
ax.set(xlim=(-3, 3), ylim=(-3, 3))
![enter image description here]()
Конечно, это можно сделать программно, захватив ограничения по оси, (ax.get_xlim()
и т.д.), но что a) делает несколько дополнительных шагов и b) является хрупким в случаях, когда больше данных может оказаться на графике и сдвиг пределов. (На самом деле в некоторых случаях просто добавление самой постоянной линии растягивает оси).
Было бы предпочтительнее просто, например, ax.axdline(ls="--", c=".3")
, но неясно, существует ли что-то подобное в кодовой базе matplotlib. Все, что вам нужно сделать, это изменить код axhline
на график из [0, 1]
в координатах осей для x
и y
, я думаю.
Ответы
Ответ 1
Построение диагональной линии, основанной на нижнем левом верхнем правом углу экрана, довольно просто, вы можете просто использовать ax.plot(ax.get_xlim(), ax.get_ylim(), ls="--", c=".3")
. Метод ax.get_xlim()
будет просто возвращать текущие значения оси x (и аналогично для оси y).
Однако, если вы хотите иметь возможность масштабирования с помощью графика, это становится немного более сложным, так как диагональная линия, которую вы построили, не изменится, чтобы соответствовать вашим новым xlims и ylims.
В этом случае вы можете использовать обратные вызовы, чтобы проверить, изменились ли xlims (или ylims) и соответственно изменили данные в диагональной строке (как показано ниже). Я нашел методы для обратных вызовов в в этом примере. Дополнительную информацию можно найти здесь
import numpy as np
import matplotlib.pyplot as plt
mean, cov = [0, 0], [(1, .6), (.6, 1)]
x, y = np.random.multivariate_normal(mean, cov, 100).T
y += x + 1
f, ax = plt.subplots(figsize=(6, 6))
ax.scatter(x, y, c=".3")
ax.set(xlim=(-3, 3), ylim=(-3, 3))
# Plot your initial diagonal line based on the starting
# xlims and ylims.
diag_line, = ax.plot(ax.get_xlim(), ax.get_ylim(), ls="--", c=".3")
def on_change(axes):
# When this function is called it checks the current
# values of xlim and ylim and modifies diag_line
# accordingly.
x_lims = ax.get_xlim()
y_lims = ax.get_ylim()
diag_line.set_data(x_lims, y_lims)
# Connect two callbacks to your axis instance.
# These will call the function "on_change" whenever
# xlim or ylim is changed.
ax.callbacks.connect('xlim_changed', on_change)
ax.callbacks.connect('ylim_changed', on_change)
plt.show()
Обратите внимание: если вы не хотите, чтобы диагональная линия менялась с увеличением, вы просто удаляете все ниже diag_line, = ax.plot(...
Ответ 2
Нанесение диагонали из левого нижнего в верхние правые углы вашего сюжета будет выполняться с помощью следующих
ax.plot([0, 1], [0, 1], transform=ax.transAxes)
Используя transform=ax.transAxes
, поставленные координаты x
и y
интерпретируются как координаты осей вместо координат данных.
Это, как указывал @fqq, является только линией, когда ваши пределы x
и y
равны. Чтобы нарисовать линию y=x
таким образом, чтобы она всегда простиралась до пределов вашего сюжета, подход, подобный тому, который был задан @Ffisegydd, будет работать и может быть записан как следующая функция.
def add_identity(axes, *line_args, **line_kwargs):
identity, = axes.plot([], [], *line_args, **line_kwargs)
def callback(axes):
low_x, high_x = axes.get_xlim()
low_y, high_y = axes.get_ylim()
low = max(low_x, low_y)
high = min(high_x, high_y)
identity.set_data([low, high], [low, high])
callback(axes)
axes.callbacks.connect('xlim_changed', callback)
axes.callbacks.connect('ylim_changed', callback)
return axes
Пример использования:
import numpy as np
import matplotlib.pyplot as plt
mean, cov = [0, 0], [(1, .6), (.6, 1)]
x, y = np.random.multivariate_normal(mean, cov, 100).T
y += x + 1
f, ax = plt.subplots(figsize=(6, 6))
ax.scatter(x, y, c=".3")
add_identity(ax, color='r', ls='--')
plt.show()
Ответ 3
Я решаю таким образом:
ident = [0.0, 1.0]
plt.plot(ident,ident)