real - python graficos 2d
¿Tiene matplotlib una función para dibujar líneas diagonales en coordenadas de eje? (2)
Matplotlib Axes tiene las funciones axhline
y axvline
para dibujar líneas horizontales o verticales en una coordenada y o dada (respectivamente) independientemente de la escala de datos en un Axes.
¿Existe una función similar para trazar una diagonal constante? Por ejemplo, si tengo un diagrama de dispersión de variables con un dominio similar, a menudo es útil saber si caen por encima o por debajo de la línea de 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))
Por supuesto, esto se puede hacer programáticamente capturando los límites del eje, ( ax.get_xlim()
, etc.), pero a) toma algunos pasos adicionales yb) es frágil en los casos en que más datos pueden terminar en el gráfico y Cambia los límites. (En realidad, en algunos casos, solo la adición de la línea constante estira los ejes).
Sería preferible hacer solo, por ejemplo, ax.axdline(ls="--", c=".3")
, pero no está claro si existe algo como esto en el código base de matplotlib. Todo lo que tendría que hacer sería modificar el código de la axhline
del axhline
para trazar desde [0, 1]
en las coordenadas de los ejes tanto para x
como para y
, creo.
Dibujar una diagonal desde la esquina inferior izquierda a la esquina superior derecha de su parcela se lograría de la siguiente manera:
ax.plot([0, 1], [0, 1], transform=ax.transAxes)
Usando transform=ax.transAxes
, las coordenadas y
se interpretan como coordenadas de ejes en lugar de coordenadas de datos .
Esto, como lo señaló @fqq, es solo la línea de identidad cuando sus límites x
e y
son iguales. Para dibujar la línea y=x
manera que siempre se extienda a los límites de su trazado, funcionará un enfoque similar al dado por @Ffisegydd, y se puede escribir como la siguiente función.
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
Ejemplo de uso:
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()
Trazar una línea diagonal desde la parte inferior izquierda a la parte superior derecha de la pantalla es bastante simple, simplemente puede usar ax.plot(ax.get_xlim(), ax.get_ylim(), ls="--", c=".3")
. El método ax.get_xlim()
simplemente devolverá los valores actuales del eje x (y de manera similar para el eje y).
Sin embargo, si desea poder hacer zoom con su gráfico, entonces se vuelve un poco más complicado, ya que la línea diagonal que ha trazado no cambiará para coincidir con sus nuevos límites y límites.
En este caso, puede utilizar las devoluciones de llamada para verificar cuándo han cambiado los xlims (o los ylims) y cambiar los datos en su línea diagonal en consecuencia (como se muestra a continuación). Encontré los métodos para devoluciones de llamada en este ejemplo . Más información también se puede encontrar here
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()
Tenga en cuenta que si no desea que la línea diagonal cambie con el zoom, simplemente elimine todo lo que se encuentra debajo de diag_line, = ax.plot(...