Как использовать `lmplot` для построения линейной регрессии без перехвата?

lmplot в моделях регрессии с морским концом с перехватом. Однако иногда я хочу подгонять модели регрессии без перехвата, т.е. Регрессии через начало координат.

Например:

In [1]: import numpy as np
   ...: import pandas as pd
   ...: import seaborn as sns
   ...: import matplotlib.pyplot as plt
   ...: import statsmodels.formula.api as sfa
   ...: 

In [2]: %matplotlib inline
In [3]: np.random.seed(2016)
In [4]: x = np.linspace(0, 10, 32)
In [5]: y = 0.3 * x + np.random.randn(len(x))
In [6]: df = pd.DataFrame({'x': x, 'y': y})
In [7]: r = sfa.ols('y ~ x + 0', data=df).fit()
In [8]: sns.lmplot(x='x', y='y', data=df, fit_reg=True)
Out[8]: <seaborn.axisgrid.FacetGrid at 0xac88a20>

введите описание изображения здесь

Рисунок, который я хотел:

In [9]: fig, ax = plt.subplots(figsize=(5, 5))
   ...: ax.scatter(x=x, y=y)
   ...: ax.plot(x, r.fittedvalues)
   ...: 
Out[9]: [<matplotlib.lines.Line2D at 0x5675a20>]

введите описание изображения здесь

Ответ 1

Seaborn API не позволяет напрямую изменять модель линейной регрессии.

Цепочка вызовов:

  • в какой-то момент вызывается _RegressionPlotter.plot() для создания сюжета
  • который вызывает _RegressionPlotter.lineplot() для выполнения графика соответствия
  • который сам по себе вызывает fit_regression, который находится в модуле regression
  • который, в свою очередь, вызывает много методов регрессии морского происхождения, таких как self.fit_fast(grid) в вашем случае.

Чтобы использовать другую регрессионную модель, вы можете:

  • Обезьяна исправит класс _RegressionPlotter и изменит поведение lineplot()
  • Обезьяна исправляет метод fit_regression() или fit_fast() в модуле регрессии

Чтобы сделать такой патч на морскую обезьяну, вы можете сослаться на ответ, который я недавно дал, который делает такой же взлом. Это плохо, и Санта не может быть счастливым. Это означает, что вы динамически модифицируете seaborn для вашей цели.

Конечно, вам нужно будет реализовать собственную регрессионную модель, чтобы иметь закон в for y = a * x вместо y = (a * x) + b. Важность beingernest уже указана в комментарии к этому такому вопросу.


Изящным способом было бы построить собственный сюжет, но вы уже ответили на этот вопрос в своем собственном вопросе.

Цитирую свой вопрос (я не проверял предоставленный код):

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import statsmodels.formula.api as sfa

np.random.seed(2016)
x = np.linspace(0, 10, 32)
y = 0.3 * x + np.random.randn(len(x))
df = pd.DataFrame({'x': x, 'y': y})
r = sfa.ols('y ~ x + 0', data=df).fit()
fig, ax = plt.subplots(figsize=(5, 5))
ax.scatter(x=x, y=y)
ax.plot(x, r.fittedvalues)

Ответ 2

Если это только для целей отображения, вы можете обойти и изменить y-тики, регулируя их с помощью ваших данных.

Вы можете сделать что-то вроде:

sns.lmplot(x='x', y='y', data=df, fit_reg=True)
y_ticks = [int(round(ytick - np.mean(y), 0)) for ytick in plt.gca().get_yticks()]
plt.gca().set_yticklabels(y_ticks)

Имейте в виду, что это не изменит ни саму линию, ни какие-либо внутренние компоненты, а только готовую визуализацию.

Ответ 3

Соответствует ли это вашей цели?

sns.lmplot(x='x', y='y', data=df, fit_reg=False)