简体   繁体   English

为什么statsmodels的OLS中的四次线性回归不匹配LibreOffice Calc?

[英]Why doesn't a quartic linear regression in statsmodels' OLS match LibreOffice Calc?

I'm using statsmodels' OLS linear regression with the Patsy quartic formula y ~ x + I(x**2) + I(x**3) + I(x**4) but the resulting regression poorly fits the data compared to LibreOffice Calc. 我将Statsmodels的OLS线性回归与Patsy四次公式y〜x y ~ x + I(x**2) + I(x**3) + I(x**4)但所得回归结果与拟合的数据相差甚远到LibreOffice Calc。 Why doesn't this match what LibreOffice Calc produces? 为什么这与LibreOffice Calc产生的结果不匹配?

statsmodels code: statsmodels代码:

import io
import numpy
import pandas
import matplotlib
import matplotlib.offsetbox
import statsmodels.tools
import statsmodels.formula.api

csv_data = """Year,CrudeRate
1999,197.0
2000,196.5
2001,194.3
2002,193.7
2003,192.0
2004,189.2
2005,189.3
2006,187.6
2007,186.9
2008,186.0
2009,185.0
2010,186.2
2011,185.1
2012,185.6
2013,185.0
2014,185.6
2015,185.4
2016,185.1
2017,183.9
"""

df = pandas.read_csv(io.StringIO(csv_data))

cause = "Malignant neoplasms"
x = df["Year"].values
y = df["CrudeRate"].values

olsdata = {"x": x, "y": y}
formula = "y ~ x + I(x**2) + I(x**3) + I(x**4)"
model = statsmodels.formula.api.ols(formula, olsdata).fit()

print(model.params)

df.plot("Year", "CrudeRate", kind="scatter", grid=True, title="Deaths from {}".format(cause))

func = numpy.poly1d(model.params.values[::-1])
matplotlib.pyplot.plot(df["Year"], func(df["Year"]))

matplotlib.pyplot.show()

Produces the following coefficients: 产生以下系数:

Intercept    9.091650e-08
x            9.127904e-05
I(x ** 2)    6.109623e-02
I(x ** 3)   -6.059164e-05
I(x ** 4)    1.503399e-08

And the following graph: 和下图:

图1

However, if I bring the data into LibreOffice Calc, click on the plot and choose "Insert Trend Line...", select "Polynomial", enter "Degrees"=4, and select "Show Equation", the resulting trend line is different from statsmodels and appears to be a closer fit: 但是,如果我将数据带入LibreOffice Calc,请单击图并选择“插入趋势线...”,选择“多项式”,输入“度数” = 4,然后选择“显示方程式”,结果趋势线为与statsmodels不同,并且看起来更合适:

图2

The coefficients are: 系数为:

Intercept = 1.35e10
x =          2.69e7
x^2 =       -2.01e4
x^3 =          6.69
x^4 =      -0.83e-3

statsmodels version: statsmodels版本:

$ pip3 list | grep statsmodels
statsmodels                  0.9.0

Edit: Cubic also doesn't match, but quadratic does. 编辑:三次也不匹配,但是二次匹配。

Edit: Scaling down Year (and doing the same in LibreOffice) matches: 编辑:按比例缩小Year (并在LibreOffice中执行相同操作)匹配项:

df = pandas.read_csv(io.StringIO(csv_data))
df["Year"] = df["Year"] - 1998

Coefficients and plot after scaling down: 缩小后的系数和图:

Intercept    197.762384
x             -0.311548
I(x ** 2)     -0.315944
I(x ** 3)      0.031304
I(x ** 4)     -0.000833

图3

Based on comments from @Josef, the problem is that large numbers don't work with high-order polynomials and statsmodels doesn't auto-scale the domain. 根据@Josef的评论,问题在于大量数字不适用于高阶多项式,而statsmodels不能自动缩放域。 In addition, I didn't mention this in the original question because I didn't expect the domain would need to be transformed, but I also needed to predict an out-of-sample value based on the year, so I make this the end of the range: 此外,我在原始问题中没有提到这一点,因为我不希望对域进行转换,但是我还需要根据年份来预测样本外值,因此我将其设为范围的结尾:

predict_x = +5
min_scaled_domain = -1
max_scaled_domain = +1
df["Year"] = df["Year"].transform(lambda x: numpy.interp(x, (x.min(), x.max() + predict_x), (min_scaled_domain, max_scaled_domain)))

This transformation creates a well-fitted regression: 此转换创建了拟合良好的回归:

图4

If the same domain transformation is applied in LibreOffice Calc, then the coefficients match. 如果在LibreOffice Calc中应用了相同的域转换,则系数匹配。

Finally, to print the predicted value: 最后,打印预测值:

func = numpy.polynomial.Polynomial(model.params)
print(func(max_scaled_domain))

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 Statsmodels - Wald检验线性回归模型(OLS)中系数趋势的显着性 - Statsmodels - Wald Test for significance of trend in coefficients in Linear Regression Model (OLS) statsmodels 线性回归 model 由于“无效语法”而不起作用 - statsmodels linear regression model doesn't work because of the "invalid syntax" 为什么`sklearn`和`statsmodels`实现OLS回归会给出不同的R ^ 2? - Why `sklearn` and `statsmodels` implementation of OLS regression give different R^2? 为什么Statsmodels OLS不支持读取包含多个单词的列? - Why does Statsmodels OLS doesn't support reading in columns with multiple words? 使用Python的statsmodels的OLS线性回归进行曲线拟合时,如何选择公式中的常数? - When curve fitting with Python's statsmodels' OLS linear regression, how do I choose the constant in the formula? 是否有可能使用 statsmodels 中的 OLS 以手动声明某些系数的方式指定线性回归? - Is there possibility to specify a linear regression using a OLS from statsmodels in way that some coefficients are declare manually? 为什么我的自定义线性回归模型不匹配sklearn? - Why doesn't my custom made linear regression model match sklearn? 了解统计模型线性回归 - Understanding statsmodels linear regression 使用statsmodels进行线性回归 - Linear regression with statsmodels Python numpy statsmodels OLS回归特定值 - Python numpy statsmodels OLS Regression specific value
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM