如何使用`lmplot`绘制没有截距的线性回归?

Posted

技术标签:

【中文标题】如何使用`lmplot`绘制没有截距的线性回归?【英文标题】:How to use `lmplot` to plot linear regression without intercept? 【发布时间】:2016-04-16 00:22:46 【问题描述】:

seaborn 中的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>]

【问题讨论】:

不是一个选项,抱歉。 @mwaskom 未来有计划支持它吗? @mwaskom 您可能想通过一些文档链接将其作为答案发布。 @mnagel 这还不够充分吗? this question? 【参考方案1】:

这符合你的目的吗?

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

【讨论】:

我们仍然想要线性回归线,但它通过 (0,0)【参考方案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)

请注意,这不会改变线路本身或任何内部结构,只会改变现成的可视化。

【讨论】:

我认为这并不等同于拟合无截距模型。斜率也会根据是否安装截距而有所不同。 @xcmkz 是对的。它通常不会改变模型,而只是在光学上移动轴。如果模型应该反映它,我想唯一有效的选择是(i)拟合没有截距的常见线性回归(例如使用 sklearn)和(ii)将学习斜率作为单独的参与者绘制到轴上。 【参考方案3】:

seaborn API 不允许直接更改线性回归模型。

调用链是:

有时会调用 _RegressionPlotter.plot() 来生成绘图 调用_RegressionPlotter.lineplot() 执行拟合图 它本身调用位于regression 模块中的fit_regression 在您的情况下又会调用许多 seaborn 回归方法,例如 self.fit_fast(grid)

要使用不同的回归模型,您可以:

monkey 修补 _RegressionPlotter 类并更改 lineplot() 行为 monkey 修补回归模块中的fit_regression()fit_fast() 方法

要做这样的seaborn猴子补丁,可以参考an answer I made a while ago that does the same type of hack。这很糟糕,圣诞老人可能不高兴。 这意味着您可以根据预期目的动态修改 seaborn。

当然,您需要实现自己的回归模型,以便在 y = a * x 而不是 y = (a * x) + b 中有一条规律。 importanceofbeingernest 已经在评论 this SO question 中指出了这一点。


一个优雅的方法是构建你自己的情节,但你已经在你自己的问题中回答了这部分。

引用你自己的问题(我没有检查提供的代码):

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)

【讨论】:

以上是关于如何使用`lmplot`绘制没有截距的线性回归?的主要内容,如果未能解决你的问题,请参考以下文章

怎样用SPSS做一元线性回归?具体怎么检验相关性

Statsmodel 拦截与 Seaborn lmplot 拦截不同

R语言中的Theil-Sen回归分析

线性回归的基本概念以及正规方程

为啥使用 Seaborn 绘制回归时截距显示不正确?

线性回归训练数据的负R2