wake-up-neo.net

Wie füge ich in Matplotlib eine Linie hinzu, die auf der Steigung und dem Schnittpunkt basiert?

In R gibt es eine Funktion mit dem Namen abline, in der eine Linie auf der Grundlage der Spezifikation des Abschnitts (erstes Argument) und der Steigung (zweites Argument) gezeichnet werden kann. Zum Beispiel,

plot(1:10, 1:10)
abline(0, 1)

wobei die Linie mit einem Achsenabschnitt von 0 und der Steigung von 1 den gesamten Bereich der Zeichnung umfasst. Gibt es eine solche Funktion in Matplotlib?

40
hatmatrix

Viele dieser Lösungen konzentrieren sich darauf, dem Diagramm eine Linie hinzuzufügen, die zu den Daten passt. Hier ist eine einfache Lösung zum Hinzufügen einer beliebigen Linie zum Diagramm basierend auf einer Neigung und einem Schnittpunkt.

import matplotlib.pyplot as plt 
import numpy as np    

def abline(slope, intercept):
    """Plot a line from slope and intercept"""
    axes = plt.gca()
    x_vals = np.array(axes.get_xlim())
    y_vals = intercept + slope * x_vals
    plt.plot(x_vals, y_vals, '--')
43
David Marx

Ich weiß, dass diese Frage ein paar Jahre alt ist, aber da es keine akzeptierte Antwort gibt, werde ich hinzufügen, was für mich funktioniert.

Sie können einfach die Werte in Ihrem Diagramm darstellen und dann einen anderen Satz von Werten für die Koordinaten der am besten passenden Linie erstellen und über das ursprüngliche Diagramm zeichnen. Siehe zum Beispiel den folgenden Code:

import matplotlib.pyplot as plt
import numpy as np

# Some dummy data
x = [1, 2, 3, 4, 5, 6, 7]
y = [1, 3, 3, 2, 5, 7, 9]

# Find the slope and intercept of the best fit line
slope, intercept = np.polyfit(x, y, 1)

# Create a list of values in the best fit line
abline_values = [slope * i + intercept for i in x]

# Plot the best fit line over the actual values
plt.plot(x, y, '--')
plt.plot(x, abline_values, 'b')
plt.title(slope)
plt.show()
30
Steve

Ich könnte keinen Weg finden, um dies zu tun, ohne auf Rückrufe zurückzugreifen, aber das scheint ziemlich gut zu funktionieren.

import numpy as np
from matplotlib import pyplot as plt


class ABLine2D(plt.Line2D):

    """
    Draw a line based on its slope and y-intercept. Additional arguments are
    passed to the <matplotlib.lines.Line2D> constructor.
    """

    def __init__(self, slope, intercept, *args, **kwargs):

        # get current axes if user has not specified them
        if not 'axes' in kwargs:
            kwargs.update({'axes':plt.gca()})
        ax = kwargs['axes']

        # if unspecified, get the current line color from the axes
        if not ('color' in kwargs or 'c' in kwargs):
            kwargs.update({'color':ax._get_lines.color_cycle.next()})

        # init the line, add it to the axes
        super(ABLine2D, self).__init__([], [], *args, **kwargs)
        self._slope = slope
        self._intercept = intercept
        ax.add_line(self)

        # cache the renderer, draw the line for the first time
        ax.figure.canvas.draw()
        self._update_lim(None)

        # connect to axis callbacks
        self.axes.callbacks.connect('xlim_changed', self._update_lim)
        self.axes.callbacks.connect('ylim_changed', self._update_lim)

    def _update_lim(self, event):
        """ called whenever axis x/y limits change """
        x = np.array(self.axes.get_xbound())
        y = (self._slope * x) + self._intercept
        self.set_data(x, y)
        self.axes.draw_artist(self)
9
ali_m
X = np.array([1, 2, 3, 4, 5, 6, 7])
Y = np.array([1.1,1.9,3.0,4.1,5.2,5.8,7])

scatter (X,Y)
slope, intercept = np.polyfit(X, Y, 1)
plot(X, X*slope + intercept, 'r')
6
mok0

Ich nehme an, für den Fall von (intercept, slope) von (0, 1) könnte die folgende Funktion verwendet und erweitert werden, um andere Steigungen und Achsenabschnitte aufzunehmen, kann jedoch nicht neu angepasst werden, wenn Achsengrenzwerte geändert oder die automatische Skalierung wieder eingeschaltet wird.

def abline():
    gca = plt.gca()
    gca.set_autoscale_on(False)
    gca.plot(gca.get_xlim(),gca.get_ylim())

import matplotlib.pyplot as plt
plt.scatter(range(10),range(10))
abline()
plt.draw()
4
hatmatrix

Hier ist eine mögliche Problemumgehung: Ich habe meine Schnittpunktkoordinaten als x_intercept und y_intercept gespeichert und die Steigung (m) als my_slope gespeichert, die durch die bekannte Gleichung ( m = (y2-y1)/(x2-x1) oder auf welche Weise auch immer Sie es gefunden haben. 

Mit der anderen bekannten allgemeinen Gleichung für eine Zeile y = mx + q definiere ich die Funktion find_second_point, die zuerst q (seit m, x und y sind bekannt) und berechnen dann einen anderen zufälligen Punkt, der zu dieser Linie gehört. 

Sobald ich die beiden Punkte (den ursprünglichen x_intercept, y_intercept und den neu gefundenen new_x, new_y) habe, plottiere ich das Segment einfach durch diese beiden Punkte. Hier ist der Code:

import numpy as np
import matplotlib.pyplot as plt

x_intercept = 3  # invented x coordinate
y_intercept = 2  # invented y coordinate
my_slope = 1  # invented slope value

def find_second_point(slope,x0,y0):
    # this function returns a point which belongs to the line that has the slope 
    # inserted by the user and that intercepts the point (x0,y0) inserted by the user
    q = y0 - (slope*x0)  # calculate q
    new_x = x0 + 10  # generate random x adding 10 to the intersect x coordinate
    new_y = (slope*new_x) + q  # calculate new y corresponding to random new_x created

    return new_x, new_y  # return x and y of new point that belongs to the line

# invoke function to calculate the new point
new_x, new_y = find_second_point(my_slope , x_intercept, y_intercept )

plt.figure(1)  # create new figure
plt.plot((x_intercept, new_x),(y_intercept, new_y), c='r', label='Segment')
plt.scatter(x_intercept, y_intercept, c='b', linewidths=3, label='Intercept')
plt.scatter(new_x, new_y, c='g', linewidths=3, label='New Point')
plt.legend()  # add legend to image

plt.show()

hier ist das vom Code erzeugte Bild:

result image

0
Tommaso Di Noto