Как добавить линию на основе наклона и пересечения в Matplotlib? - PullRequest
43 голосов
/ 29 октября 2011

В R есть функция с именем abline, в которой линия может быть нарисована на графике на основе спецификации пересечения (первый аргумент) и наклона (второй аргумент).Например,

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

, где линия с пересечением 0 и наклоном 1 охватывает весь диапазон графика.Есть ли такая функция в Matplotlib?

Ответы [ 6 ]

49 голосов
/ 05 мая 2017

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

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, '--')
30 голосов
/ 09 декабря 2013

Я знаю, что этому вопросу пару лет, но поскольку нет принятого ответа, я добавлю, что работает для меня.

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

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()
9 голосов
/ 16 января 2013

Я не мог придумать способ сделать это, не прибегая к обратным вызовам, но это, кажется, работает довольно хорошо.

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)
7 голосов
/ 07 мая 2014
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')
4 голосов
/ 30 октября 2011

Полагаю, что в случае (intercept, slope) из (0, 1) следующую функцию можно использовать и расширять для учета других уклонов и пересечений, но не перенастраивать, если изменяются пределы оси или снова включается автоматическое масштабирование.

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()
0 голосов
/ 23 октября 2018

Вот возможный обходной путь, к которому я пришел: предположим, мои координаты перехвата сохранены как x_intercept и y_intercept, а наклон ( m ) сохранен как my_slope который был найден по известному уравнению m = (y2-y1) / (x2-x1) , или каким-либо другим способом вам удалось его найти.

Используя другое известное общее уравнение для линии y = mx + q , я определяю функцию find_second_point, которая сначала вычисляет q (поскольку известны m , x и y ), а затем вычисляется еще одна случайная точка, принадлежащая этой линии.

Как только у меня появятся две точки (начальная x_intercept, y_intercept и недавно найденная new_x, new_y), я просто нанесу отрезок на эти две точки. Вот код:

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

вот изображение, сгенерированное кодом:

result image

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...