使用 python 做线性回归分析有好几种方式,常要的分别是 scipy 包,statsmodels 包,以及 sklearn 包。但是,这些包目前都不能处理共线性,即自动剔除部分共线性的变量,需要自己去编函数,这一点不如 spss 或 r 语言。
假设有下面的数据存储在 excel 文件里面:
不良贷款各项贷款余额本年累计应收贷款贷款项目个数本年固定资产投资额
0.9
67.3
6.8
5
51.9
1.1
111.3
19.8
16
90.9
4.8
173.0
7.7
17
73.7
3.2
80.8
7.2
10
14.5
7.8
199.7
16.5
19
63.2
2.7
16.2
2.2
1
2.2
1.6
107.4
10.7
17
20.2
12.5
185.4
27.1
18
43.8
1.0
96.1
1.7
10
55.9
2.6
72.8
9.1
14
64.3
0.3
64.2
2.1
11
42.7
4.0
132.2
11.2
23
76.7
0.8
58.6
6.0
14
22.8
3.5
174.6
12.7
26
117.1
10.2
263.5
15.6
34
146.7
3.0
79.3
8.9
15
29.9
0.2
14.8
0.6
2
42.1
0.4
73.5
5.9
11
25.3
1.0
24.7
5.0
4
13.4
6.8
139.4
7.2
28
64.3
11.6
368.2
16.8
32
163.9
1.6
95.7
3.8
10
44.5
1.2
109.6
10.3
14
67.9
7.2
196.2
15.8
16
39.7
3.2
102.2
12.0
10
97.1
首先使用 pandas 读取 excel 数据:
import pandas as pd
# 读取 excel 数据,引号里面是 excel 文件在电脑的存储位置
datas = pd.read_excel(r'D:\Users\chen_\git\Statistics-book\datas\linear_regression.xlsx')
1
2
3
4
1. 用 scipy 包
scipy.stats 中的 linregress 函数可以做一元线性回归。假如因变量为 “不良贷款”,自变量为 “各项贷款余额”,全部 python 代码如下:
import scipy.stats as st
import pandas as pd
datas = pd.read_excel(r'D:\Users\chen_\git\Statistics-book\datas\linear_regression.xlsx') # 读取 excel 数据,引号里面是 excel 文件的位置
y = datas.iloc[:, 1] # 因变量为第 2 列数据
x = datas.iloc[:, 2] # 自变量为第 3 列数据
# 线性拟合,可以返回斜率,截距,r 值,p 值,标准误差
slope, intercept, r_value, p_value, std_err = st.linregress(x, y)
print(slope)# 输出斜率
print(intercept) # 输出截距
print(r_value**2) # 输出 r^2
1
2
3
4
5
6
7
8
9
10
11
12
13
scipy 中的回归分析比较简单,目前只能做一元线性回归,也不能用来做预测。
2. 用 statsmodels 包
import pandas as pd
import statsmodels.api as sm
import matplotlib.pyplot as plt
datas = pd.read_excel(r'D:\Users\chen_\git\Statistics-book\datas\linear_regression.xlsx') # 读取 excel 数据,引号里面是 excel 文件的位置
y = datas.iloc[:, 1] # 因变量为第 2 列数据
x = datas.iloc[:, 2] # 自变量为第 3 列数据
x = sm.add_constant(x) # 若模型中有截距,必须有这一步
model = sm.OLS(y, x).fit() # 构建最小二乘模型并拟合
print(model.summary()) # 输出回归结果
# 画图
# 这两行代码在画图时添加中文必须用
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False
predicts = model.predict() # 模型的预测值
x = datas.iloc[:, 2] # 自变量为第 3 列数据
plt.scatter(x, y, label='实际值') # 散点图
plt.plot(x, predicts, color = 'red', label='预测值')
plt.legend() # 显示图例,即每条线对应 label 中的内容
plt.show() # 显示图形
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
统计结果如下:
画出的实际值与预测值如下图:
注意:若导入包时使用命令 import statsmodels.formula.api as sm, 则在回归分析时不用添加截距 add_constant,但是必须使用统计语言给出模型信息,代码如下:
import pandas as pd
import statsmodels.formula.api as sm
import matplotlib.pyplot as plt
datas = pd.read_excel(r'D:\Users\chen_\git\Statistics-book\datas\linear_regression.xlsx') # 读取 excel 数据,引号里面是 excel 文件的位置
model = sm.ols('不良贷款~各项贷款余额', datas).fit() # 构建最小二乘模型并拟合,
#此时不用单独输入 x,y了,而是将自变量与因变量用统计语言公式表示,将全部数据导入
print(model.summary()) # 输出回归结果
# 画图
# 这两行代码在画图时添加中文必须用
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False
predicts = model.predict() # 模型的预测值
y = datas.iloc[:, 1] # 因变量为第 2 列数据
x = datas.iloc[:, 2] # 自变量为第 3 列数据
plt.scatter(x, y, label='实际值')
plt.plot(x, predicts, color = 'red', label='预测值')
plt.legend() # 显示图例,即每条线对应 label 中的内容
plt.show() # 显示图形
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
在多元回归中,只需把自变量改为多列数据即可,假如不良贷款为因变量,从第3列到第6列都是因变量,则使用 statsmodels 包的全部 python 代码如下:
import pandas as pd
import statsmodels.api as sm
import matplotlib.pyplot as plt
datas = pd.read_excel(r'D:\Users\chen_\git\Statistics-book\datas\linear_regression.xlsx') # 读取 excel 数据,引号里面是 excel 文件的位置
y = datas.iloc[:, 1] # 因变量为第 2 列数据
x = datas.iloc[:, 2:6] # 自变量为第 3 列到第 6 列数据
x = sm.add_constant(x) # 若模型中有截距,必须有这一步
model = sm.OLS(y, x).fit() # 构建最小二乘模型并拟合
print(model.summary()) # 输出回归结果
1
2
3
4
5
6
7
8
9
10
回归结果:
3. 用 sklearn 包
sklearn 包机器学习中常见的 python 包,可以用来做统计分析时,但它并不能像 statsmodels 那样生成非常详细的统计分析结果。一元回归时,自变量与因变量都需要处理下,对于上面同样的例子:
import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
from sklearn.linear_model import LinearRegression
datas = pd.read_excel(r'D:\Users\chen_\git\Statistics-book\datas\linear_regression.xlsx') # 读取 excel 数据,引号里面是 excel 文件的位置
y = datas.iloc[:, 1] # 因变量为第 2 列数据
x = datas.iloc[:, 2] # 自变量为第 3 列数据
# 将 x,y 分别增加一个轴,以满足 sklearn 中回归模型认可的数据
x = x[:, np.newaxis]
y = y[:, np.newaxis]
model = LinearRegression() # 构建线性模型
model.fit(x, y) # 自变量在前,因变量在后
predicts = model.predict(x) # 预测值
R2 = model.score(x, y) # 拟合程度 R2
print('R2 = %.2f' % R2) # 输出 R2
coef = model.coef_ # 斜率
intercept = model.intercept_ # 截距
print(model.coef_, model.intercept_) # 输出斜率和截距
# 画图
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False
y = datas.iloc[:, 1] # 因变量为第 2 列数据
x = datas.iloc[:, 2] # 自变量为第 3 列数据
plt.scatter(x, y, label='实际值') # 散点图
plt.plot(x, predicts, color = 'red', label='预测值')
plt.legend() # 显示图例,即每条线对应 label 中的内容
plt.show() # 显示图形
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
用 sklearn 做多元回归时,自变量不需要单独处理了,全部代码如下:
import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
from sklearn.linear_model import LinearRegression
datas = pd.read_excel(r'D:\Users\chen_\git\Statistics-book\datas\linear_regression.xlsx') # 读取 excel 数据,引号里面是 excel 文件的位置
y = datas.iloc[:, 1] # 因变量为第 2 列数据
x = datas.iloc[:, 2:6] # 自变量为第 3 列到第 6 列数据
# 将 y 分别增加一个轴,以满足 sklearn 中回归模型认可的数据
# 此时由于 x 是多元变量,则不用添加新的轴了
y = y[:, np.newaxis]
model = LinearRegression() # 构建线性模型
model.fit(x, y) # 自变量在前,因变量在后
predicts = model.predict(x) # 预测值
R2 = model.score(x, y) # 拟合程度 R2
print('R2 = %.3f' % R2) # 输出 R2
coef = model.coef_ # 斜率
intercept = model.intercept_ # 截距
print(model.coef_, model.intercept_) # 输出斜率和截距