it-swarm.com.de

Hat matplotlib eine Funktion zum Zeichnen diagonaler Linien in Achskoordinaten?

Matplotlib-Achsen haben die Funktionen axhline und axvline zum Zeichnen horizontaler oder vertikaler Linien an einer gegebenen y- oder x-Koordinate (jeweils) unabhängig von der Datenskala auf einer Achse.

Gibt es eine ähnliche Funktion zum Zeichnen einer konstanten Diagonale? Wenn ich beispielsweise ein Streudiagramm von Variablen mit einer ähnlichen Domäne habe, ist es oft nützlich zu wissen, ob sie über oder unter der Zeile von y = x liegen:

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

Dies kann natürlich programmgesteuert durch Erfassen der Achsgrenzen (ax.get_xlim() usw.) erfolgen, aber a) erfordert einige zusätzliche Schritte und b) ist spröde, wenn mehr Daten in die Grafik gelangen und die Grenzen verschieben können. (In manchen Fällen werden durch das Hinzufügen der konstanten Linie selbst die Achsen gestreckt).

Es wäre vorzuziehen, beispielsweise ax.axdline(ls="--", c=".3") zu tun, aber es ist nicht klar, ob so etwas in der Matplotlib-Codebase vorhanden ist. Alles, was Sie tun müssten, wäre, den axhline-Code so zu ändern, dass er aus [0, 1] in Achsen Koordinaten für x und y plottet, denke ich.

28
mwaskom

Das Zeichnen einer Diagonalen von links unten nach rechts oben ist recht einfach. Sie können einfach ax.plot(ax.get_xlim(), ax.get_ylim(), ls="--", c=".3") verwenden. Die Methode ax.get_xlim() liefert einfach die aktuellen Werte der x-Achse (und ähnlich für die y-Achse).

Wenn Sie jedoch mit Ihrem Diagramm zoomen möchten, wird es etwas komplizierter, da die geplante diagonale Linie nicht an Ihre neuen Xlims und Ylims angepasst wird. 

In diesem Fall können Sie Callbacks verwenden, um zu überprüfen, wann sich die Xlims (oder Ylims) geändert haben, und die Daten in Ihrer diagonalen Linie entsprechend zu ändern (wie unten gezeigt). Ich habe die Methoden für Rückrufe in diesem Beispiel gefunden. Weitere Informationen finden Sie auch hier

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()

Wenn Sie nicht möchten, dass sich die diagonale Linie beim Zoomen ändert, entfernen Sie einfach alles unter diag_line, = ax.plot(....

29
Ffisegydd

Das Zeichnen einer Diagonale von der unteren linken zur oberen rechten Ecke Ihres Diagramms wird folgendermaßen ausgeführt

ax.plot([0, 1], [0, 1], transform=ax.transAxes)

Mit transform=ax.transAxes, die angegebenen x und y Koordinaten werden als Achsen Koordinaten anstelle von Daten Koordinaten interpretiert.

Wie @fqq hervorhob, ist dies nur die Identitätslinie, wenn Ihre Grenzen x und y gleich sind. Um die Linie zu ziehen y=x so, dass es sich immer bis an die Grenzen Ihres Plots erstreckt, würde ein Ansatz ähnlich dem von @Ffisegydd funktionieren und kann als folgende Funktion geschrieben werden.

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

Anwendungsbeispiel:

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()
27
JaminSore

Ich beschließe auf diese Weise:

ident = [0.0, 1.0]
plt.plot(ident,ident)
0
volperossa