![](https://i-blog.csdnimg.cn/blog_migrate/6c465099b0b90a9638b0ea88533ccaf3.png)
目录
一、背景介绍
在宏观经济学的理论中,投资是构成GDP的一部分,我国经济增长一般都用我国的GDP总量来衡量。从这一点来说,投资与经济增长之间应该存在着相关关系。由于投资与经济增长存在着相互作用,因此,从理论上讲固定资产投资对经济增长存在着相互作用、相互影响的关系。固定资产投资的增加可以推动经济总量的增长,同时经济增长的水平在一定程度上也决定着固定资产总量的水平。为了探讨其具体的定量关系,本文将根据北京市统计年鉴的2005年-2018年各行业固定资产投资额和GDP数据,进行回归分析,探讨行业固定资产投资额对行业GDP的贡献情况,并分析全市GDP数据与各行业投资额之间的量化关系。
数据来源:北京市统计局1
下述代码 阅读/运行 须知:
为了第二、第三及第四部分的内容展示上稍微精简一些,将部分可能重复用到的代码进行了打包工作,统一在第五部分展示,即 分析函数化Codes 部分,因此如需运行第二、第三及第四部分的代码,请先运行第五部分的代码。
二、数据探索
# 读取数据
sheet_names = ["北京市投资与gdp","各行业gdp","各行业固定资产投资"]
names = ["年份","全市","建筑业","批发和零售业","交通运输、仓储和邮政业","住宿和餐饮业" ,
"信息传输、软件和信息技术服务业","金融业","房地产业","租赁和商务服务业",
"科学研究和技术服务业","水利、环境和公共设施管理业","居民服务、修理和其他服务业",
"教育","卫生和社会工作","文化、体育和娱乐业","公共管理、社会保障和社会组织"]
# data = pd.read_excel('20200306 各行业投资与经济增长回归(慕).xls',sheet_name=sheet_names[1],
# skiprows=3,names =names,index_col=0,dtypes={names[1]:np.float})
industry_gdp_data = pd.read_excel('20200306 各行业投资与经济增长回归(慕).xls',sheet_name=sheet_names[1],
header=0,index_col=0)
industry_fac_data = pd.read_excel('20200306 各行业投资与经济增长回归(慕).xls',sheet_name=sheet_names[2],
header=0,index_col=0)
可视化了解各行业GDP与固定资产投资的关系
# 画散点图
fig = plt.figure(figsize=(180,70))
for i in range(1,len(names)):
ax = fig.add_subplot(2,8,i)
ax.scatter(industry_fac_data[names[i]],industry_gdp_data[names[i]],s=500)
plt.title(names[i],fontsize=56)
plt.xlabel(names[i]+'投资额',fontsize=48)
plt.ylabel(names[i]+'GDP',fontsize=48)
plt.xticks(fontsize=48)
plt.yticks(fontsize=48)
plt.show()
# fig.tight_layout() #自动调整格式
# 全市各行业的GDP与对应行业投资额的相关性
corr_gdp_industry_list = []
for i in range(1,len(names)):
corr_gdp_industry_list.append(industry_fac_data[names[i]].corr(industry_gdp_data[names[i]]))
figure = plt.figure(figsize=(20,10))
corr_bar = plt.bar(names[1:len(names)],corr_gdp_industry_list)
plt.xticks(rotation=60,fontsize=12)
for bar in corr_bar:
height = bar.get_height()
plt.text(bar.get_x() + bar.get_width() / 2, height, str(('%.2f')%height), ha='center', va='bottom',fontsize=14)
plt.axhline(0.9,color='r')
plt.xticks(fontsize=14)
plt.yticks(fontsize=14)
plt.title('全市各行业的GDP与对应行业投资额相关性条形图',fontsize=16)
plt.show()
小结:
通过上图各行业GDP与固定资产投资的关系散点图、相关性结果可知
- 交通运输仓储和邮政业、信息传输软件和信息技术服务业、房地产业、水利环境和公共设施管理业 4个行业的投资额与其各自的GDP,具有较好的相关性,超过0.9,其他行业的gdp和投资额的相关性还需要进一步来判断。
- 另外,全市的投资额和GDP,也具有很强的相关性。
箱型图,了解各行业GDP数据分布情况
title_name = '各行业GDP数据箱线图'
sub_ylabel = "GDP"
industry_boxplot_mu(industry_gdp_data,title_name,sub_ylabel)
plt.figure(figsize=(15,10))
industry_gdp_data.ix[:,1:].boxplot(vert=False,
showmeans=True, # 以点的形式显示均值
meanprops = {'marker':'D','markerfacecolor':'indianred','linewidth':1} # 设置均值点的属性,点的形状、填充色
)
plt.xlabel('GDP',fontsize=14)
plt.ylabel('行业',fontsize=14)
plt.xticks(rotation=0,fontsize=12)
plt.yticks(fontsize=12)
plt.title('各行业GDP数据箱线图',fontsize=18)
小结:
通过各行业GDP的箱线图可知,各行业的GDP数据均无异常,但部分行业的GDP存在左偏或者右偏现象。
- 批发和零售业、住宿和餐饮业、左偏现象比较明显;
- 信息传输软件和信息服务业、金融业、科学研究和技术服务业、水利环境额 公共设施管理业、教育、卫生和社会工作,右偏现象较明显
箱型图,了解各行业投资额数据分布情况
title_name = '各行业 投资额数据箱线图'
sub_ylabel = "投资额"
industry_boxplot_mu(industry_fac_data,title_name,sub_ylabel)
plt.figure(figsize=(15,10))
industry_fac_data.ix[:,1:].boxplot(vert=False,
showmeans=True, # 以点的形式显示均值
meanprops = {'marker':'D','markerfacecolor':'indianred','linewidth':1} # 设置均值点的属性,点的形状、填充色
)
plt.title('各行业投资额数据箱线图',fontsize=16)
plt.xlabel('GDP',fontsize=14)
plt.ylabel('行业',fontsize=14)
plt.xticks(rotation=0,fontsize=12)
plt.yticks(fontsize=12)
plt.show()
小结:
通过各行业投资额的箱线图可知,行业的投资额历年数据,也存在一定的偏态,并且部分行业的投资额变化较大。
- 诸如建筑业、批发和零售业、交通运输仓储和邮政业、信息传输软件和信息技术服务业、租赁和商务服务业、文化体育和娱乐业,根据箱线图判断,存在异常数据;
- 除过上述含异常值的行业,其余行业中,金融业、房地产业、科学研究和技术服务业、教育、卫生和社会工作,投资额存在左偏现象;
- 而水利环境和公共设施管理业、居民服务修理和其他服务业、公共管理社会保障和社会组织,投资额存在右偏现象。
可视化了解各行业GDP之间的关系
(1)画矩阵散点图
'''
kdeplot(核密度估计图):核密度估计(kernel density estimation)是在概率论中用来估计未知的密度函数,
属于非参数检验方法之一。通过核密度估计图可以比较直观的看出数据样本本身的分布特征。
distplot :displot()集合了matplotlib的hist()与核函数估计kdeplot的功能,
增加了rugplot分布观测条显示与利用scipy库fit拟合参数分布的新颖用途。
'''
g = sns.PairGrid(industry_gdp_data)
g.map_diag(sns.distplot) #设置对角线图表
g.map_upper(plt.scatter, color = 'r') #设置对角线上端图表
g.map_lower(sns.kdeplot, cmap='Blues_d') #设置对角线下端图表
(2) 画相关系数矩阵图
gdp_corr = industry_gdp_data.corr() # gdp相关系数矩阵
vmax=gdp_corr.max().max()
vmin=gdp_corr.min().min()
print("最小相关系数:",vmin)
plt.figure(figsize=(15,15))
'''
annot=True,意思是显式热力图上的数值大小
square=True,意思是将图变成一个正方形,默认是一个矩形
cmap="Blues"是一种模式,就是图颜色配置方案
vmax是显示最大值
'''
sns.heatmap(gdp_corr,annot=True,vmax=vmax,vmin=vmin,square=True,cmap='Blues')
小结:
通过散点图和相关系数矩阵图,均可以发现,各行业的GDP之间具有较强的正相关,普遍相关系数,均在0.8以上。
可视化了解各行业固定资产投资的关系
(1) 画矩阵散点图
'''
kdeplot(核密度估计图):核密度估计(kernel density estimation)是在概率论中用来估计未知的密度函数,
属于非参数检验方法之一。通过核密度估计图可以比较直观的看出数据样本本身的分布特征。
distplot :displot()集合了matplotlib的hist()与核函数估计kdeplot的功能,
增加了rugplot分布观测条显示与利用scipy库fit拟合参数分布的新颖用途。
'''
g = sns.PairGrid(industry_fac_data)
g.map_diag(sns.distplot) #设置对角线图表
g.map_upper(plt.scatter, color = 'r') #设置对角线上端图表
g.map_lower(sns.kdeplot, cmap='Blues_d') #设置对角线下端图表
(2)画相关系数矩阵图
fac_corr = industry_fac_data.corr() # gdp相关系数矩阵
vmax=fac_corr.max().max()
vmin=fac_corr.min().min()
print("最小相关系数:",vmin)
# print("最大相关系数:",vmax)
plt.figure(figsize=(15,15))
sns.heatmap(fac_corr,annot=True,vmax=vmax,vmin=vmin,square=True,cmap='Blues')
plt.title("各行业固定资产投资的关系相关系数矩阵图",fontsize=18)
小结:
对于各行业的投资额,通过散点图矩阵和相关系数矩阵可以发现,
- 行业间的投资额的相关性,相对行业GDP的相关性要弱一些,并且部分行业间投资额具有负相关性。
- 建筑业、文化体育和娱乐业、公共管理社会保障和社会组织,相对来说,普遍与其他行业的相关性较弱。
通过上述分析,信息传输软件和信息技术服务业、房地产业、水利环境和公共设施管理业 3个行业的投资额与其各自的GDP,具有较好的线性关系;大部分行业的历年GDP和投资额,存在左偏或者右偏现象;行业GDP之间相关性普遍较强,而行业投资额间相关性则分化比较大。
三、信息传输、软件和信息技术服务业回归分析
1. 投资额和GDP可视化
industry_name = "信息传输、软件和信息技术服务业"
ytrain = industry_gdp_data[industry_name]
xtrain = industry_fac_data[industry_name]
2. 回归分析
(1)模型一:原始数据
model,y_pre = simple_regression_mu(ytrain,xtrain)
model.summary()
小结
模型通过检验,模型的系数通过检验,但是模型的常数项没有通过检验。另外,D.W.的值为2.152,根据DW检验表,DW取值在(dU, 4- dU)之间,接受原假设H0 ,认为ut 非自相关,即在信息传输、软件和信息技术服务业,残差非自相关,但也有可能残差具有较高的自相关性。
# 拟合结果可视化
visual_regression_result(range(len(ytrain)),ytrain,y_pre)
# visual_regression_result(model,sm.add_constant(xtrain))
** 残差分析**
线性模型的残差通常具有正太分布。我们可以绘制残差密度来检查正态性。
fig = plt.figure(figsize=(15,5))
ax = fig.add_subplot(121)
# model.resid.plot.density() #残差密度图
model.resid.hist(bins=5,alpha = 0.5)
model.resid.plot(kind = 'kde', secondary_y=True)
ax.set_title('密度直方图')
# plt.grid()
ax2 = fig.add_subplot(122)
# qq图
stats.probplot(model.resid, dist="norm", plot=plt)
plt.show()
# 残差正态性检验
from scipy.stats import kstest # K-S检验:特点是比较严格,基于的原理是CDF,理论上可以检验任何分布
ks_result = kstest(model.resid,'norm')
print('kstest检验:',ks_result)
from scipy.stats import shapiro # Shapiro检验:专门用来检验正态分布 shapiro 不适合做样本数>5000的正态性检验,检验结果的P值可能不准确
shap_result = shapiro(model.resid)
print('shapiro检验:',shap_result)
from scipy.stats import normaltest # Normal检验:原理是基于数据的skewness和kurtosis
norm_result = normaltest(model.resid,axis=None)
print('normaltest检验:',norm_result)
kstest检验2: KstestResult(statistic=0.5714285714285714, pvalue=7.456196123263218e-05)
shapiro检验: (0.901134729385376, 0.11714380979537964)
normaltest检验: NormaltestResult(statistic=6.129670593453145, pvalue=0.04666152653777272)
# 定量判断 残差同方差检验
# White's Test
white_test = sm.stats.diagnostic.het_white(model.resid, exog = model.model.exog)
print('模型方差齐性检验统计量:%.2f,P值:%.4f,Fvalue:%.2f,F_pvalue:%.2f:' %(white_test))
# model.model.exog
# 定性判断 残差同方差检验 及残差的自相关性判断
# 判断标准:如果残差在参考线两侧均匀分布,则意味着异方差性较弱;而如果呈现出明显的不均匀分布,则意味着存在明显的异方差性。
residual_scatter_mu(model)
模型方差齐性检验统计量:1.95,P值:0.3779,Fvalue:0.89,F_pvalue:0.44
小结:
根据怀特检验,残差通过方差齐性检验,但是通过残差序列图可以发现,残差还是存在一定的异方差情况;另外,根据残差序列图和残差的散点图,可以发现残差具有一定的自相关性
模型评价
print('评价模型标准-相对误差绝对值平均MAPE (Mean Absolute Percentage Error):%.3f'
%(mean_absolute_per_err(y_pre,ytrain)))
长度: 14
评价模型标准-相对误差绝对值平均MAPE (Mean Absolute Percentage Error):0.134
(2) 模型二:消除异方差
# 通过对变量取对数消除异方差
log_ytrain = np.log(ytrain)
log_xtrain = np.log(xtrain)
gdp_fac_graph_mu(log_ytrain,log_xtrain)
model2 ,log_y_pre= simple_regression_mu(log_ytrain,log_xtrain)
model2.summary()
# 拟合结果可视化
visual_regression_result(range(len(log_ytrain)),ytrain,np.exp(log_y_pre))
残差分析
fig = plt.figure(figsize=(15,5))
ax = fig.add_subplot(121)
# model.resid.plot.density() #残差密度图
model2.resid.hist(bins=5,alpha = 0.5)
model2.resid.plot(kind = 'kde', secondary_y=True)
ax.set_title('密度直方图')
# plt.grid()
ax2 = fig.add_subplot(122)
# qq图
stats.probplot(model2.resid, dist="norm", plot=plt)
plt.show()
# 残差正态性检验
from scipy.stats import kstest # K-S检验:特点是比较严格,基于的原理是CDF,理论上可以检验任何分布
ks_result = kstest(model2.resid,'norm')
print('kstest检验:',ks_result)
from scipy.stats import shapiro # Shapiro检验:专门用来检验正态分布 shapiro 不适合做样本数>5000的正态性检验,检验结果的P值可能不准确
shap_result = shapiro(model2.resid)
print('shapiro检验:',shap_result)
from scipy.stats import normaltest # Normal检验:原理是基于数据的skewness和kurtosis
norm_result = normaltest(model2.resid,axis=None)
print('normaltest检验:',norm_result)
kstest检验: KstestResult(statistic=0.403305160372756, pvalue=0.014364366464748599)
shapiro检验: (0.931269645690918, 0.3178831934928894)
normaltest检验: NormaltestResult(statistic=1.9191948456802586, pvalue=0.3830470609372596)
# 定量判断 残差同方差检验(残差和自变量之间)
# White's Test
white_test = sm.stats.diagnostic.het_white(model2.resid, exog = model2.model.exog)
print('模型方差齐性检验统计量:%.2f,P值:%.4f,Fvalue:%.2f,F_pvalue:%.2f:' %(white_test))
# model.model.exog
# 定性判断 残差同方差检验 及残差的自相关性判断
# 判断标准:如果残差在参考线两侧均匀分布,则意味着异方差性较弱;而如果呈现出明显的不均匀分布,则意味着存在明显的异方差性。
residual_scatter_mu(model2)
模型方差齐性检验统计量:1.46,P值:0.4829,Fvalue:0.64,F_pvalue:0.55
模型评价
print('评价模型标准-相对误差绝对值平均MAPE (Mean Absolute Percentage Error):%.3f'
%(mean_absolute_per_err(log_y_pre,log_ytrain)))
re_log_y_pre = np.exp(log_y_pre)
print('还原数据后,评价模型标准-相对误差绝对值平均MAPE (Mean Absolute Percentage Error):%.3f'
%(mean_absolute_per_err(re_log_y_pre,ytrain)))
长度: 14
评价模型标准-相对误差绝对值平均MAPE (Mean Absolute Percentage Error):0.018
长度: 14
还原数据后,评价模型标准-相对误差绝对值平均MAPE (Mean Absolute Percentage Error):0.130
(3)模型三:模型变换 加入一阶滞后项,消除自相关
test = industry_fac_data[industry_name][1:]
test2 = pd.Series(industry_fac_data[industry_name][:-1])
test2.index = test.index
add_xtrain = pd.concat([test,test2],axis=1)
add_xtrain.columns = [industry_name,'滞后一年']
add_ytrain = industry_gdp_data[industry_name][1:]
# industry_FAC = sm.add_constant(industry_FAC) # 线性回归增加常数项 y=kx+b
# model = sm.OLS(industry_GDP, industry_FAC) # 普通最小二乘模型,ordinary least square model
# model = model.fit() #res.model.endog
# # 模型检验及系数检验
# print(industry_name+" 的回归模型检验及系数检验结果:\n")
# model.summary()
model3 ,add_y_pre= simple_regression_mu(add_ytrain,add_xtrain)
model3.summary()
# 拟合结果可视化
visual_regression_result(range(len(add_ytrain)),add_ytrain,add_y_pre)
残差分析
# plt.figure()
# model.resid.plot.density() #残差密度图
# model.resid.hist(bins=5,alpha = 0.5)
# model.resid.plot(kind = 'kde', secondary_y=True)
fig = plt.figure(figsize=(15,5))
ax = fig.add_subplot(121)
# model.resid.plot.density() #残差密度图
model3.resid.hist(bins=5,alpha = 0.5)
model3.resid.plot(kind = 'kde', secondary_y=True)
ax.set_title('密度直方图')
# plt.grid()
ax2 = fig.add_subplot(122)
# qq图
stats.probplot(model3.resid, dist="norm", plot=plt)
plt.show()
# 残差正态性检验
from scipy.stats import kstest # K-S检验:特点是比较严格,基于的原理是CDF,理论上可以检验任何分布
ks_result = kstest(model3.resid,'norm')
print('kstest检验:',ks_result)
from scipy.stats import shapiro # Shapiro检验:专门用来检验正态分布
shap_result = shapiro(model3.resid)
print('shapiro检验:',shap_result)
from scipy.stats import normaltest # Normal检验:原理是基于数据的skewness和kurtosis
norm_result = normaltest(model3.resid)
print('normaltest检验:',norm_result)
kstest检验: KstestResult(statistic=0.5384615384615384, pvalue=0.0004708705798459567)
shapiro检验: (0.9762569069862366, 0.9561669230461121)
normaltest检验: NormaltestResult(statistic=0.21037569966411002, pvalue=0.9001554126600356)
# 定性判断 残差同方差检验 及残差的自相关性判断
# 判断标准:如果残差在参考线两侧均匀分布,则意味着异方差性较弱;而如果呈现出明显的不均匀分布,则意味着存在明显的异方差性。
residual_scatter_mu(model3)
# 定量判断 残差的同方差检验
# White's Test
white_test = sm.stats.diagnostic.het_white(model3.resid, exog = model3.model.exog)
print('模型方差齐性检验统计量:%.2f,P值:%.4f,Fvalue:%.2f,F_pvalue:%.2f:' %(white_test))
# model.model.exog
模型方差齐性检验统计量:5.58,P值:0.3498,Fvalue:1.05,F_pvalue:0.46
模型评价
print('评价模型标准-相对误差绝对值平均MAPE (Mean Absolute Percentage Error):%.3f'
%(mean_absolute_per_err(add_y_pre,add_ytrain)))
长度: 13
评价模型标准-相对误差绝对值平均MAPE (Mean Absolute Percentage Error):0.093
(4)模型四 加入一阶滞后项和数据取对数
- 模型变换 加入一阶滞后项,消除自相关;
- 取对数,消除异方差
log_add_xtrain = np.log(add_xtrain)
log_add_ytrain = np.log(add_ytrain)
model4 ,log_add_y_pre= simple_regression_mu(log_add_ytrain,log_add_xtrain)
model4.summary()
# 拟合结果可视化
visual_regression_result(range(len(log_add_ytrain)),log_add_ytrain,log_add_y_pre)
残差分析
fig = plt.figure(figsize=(15,5))
ax = fig.add_subplot(121)
# model.resid.plot.density() #残差密度图
model4.resid.hist(bins=5,alpha = 0.5)
model4.resid.plot(kind = 'kde', secondary_y=True)
ax.set_title('密度直方图')
# plt.grid()
ax2 = fig.add_subplot(122)
# qq图
stats.probplot(model4.resid, dist="norm", plot=plt)
plt.show()
# 残差正态性检验
from scipy.stats import kstest # K-S检验:特点是比较严格,基于的原理是CDF,理论上可以检验任何分布
ks_result = kstest(model4.resid,'norm')
print('kstest检验:',ks_result)
from scipy.stats import shapiro # Shapiro检验:专门用来检验正态分布
shap_result = shapiro(model4.resid)
print('shapiro检验:',shap_result)
from scipy.stats import normaltest # Normal检验:原理是基于数据的skewness和kurtosis
norm_result = normaltest(model4.resid)
print('normaltest检验:',norm_result)
kstest检验: KstestResult(statistic=0.4434958990037281, pvalue=0.007560196567781911)
shapiro检验: (0.9548967480659485, 0.6739445924758911)
normaltest检验: NormaltestResult(statistic=0.5897760812235786, pvalue=0.744614949433436)
# 定性判断 残差同方差检验 及残差的自相关性判断
# 判断标准:如果残差在参考线两侧均匀分布,则意味着异方差性较弱;而如果呈现出明显的不均匀分布,则意味着存在明显的异方差性。
residual_scatter_mu(model4)
# 定量判断 残差的同方差检验
# White's Test
white_test = sm.stats.diagnostic.het_white(model4.resid, exog = model4.model.exog)
print('模型方差齐性检验统计量:%.2f,P值:%.4f,Fvalue:%.2f,F_pvalue:%.2f:' %(white_test))
# model.model.exog
模型方差齐性检验统计量:3.26,P值:0.6606,Fvalue:0.47,F_pvalue:0.79
print('评价模型标准-相对误差绝对值平均MAPE (Mean Absolute Percentage Error):%.3f'
%(mean_absolute_per_err(log_add_y_pre,log_add_ytrain)))
re_log_add_y_pre = np.exp(log_add_y_pre)
print('还原数据后,评价模型标准-相对误差绝对值平均MAPE (Mean Absolute Percentage Error):%.3f'
%(mean_absolute_per_err(re_log_add_y_pre,add_ytrain)))
长度: 13
评价模型标准-相对误差绝对值平均MAPE (Mean Absolute Percentage Error):0.012
长度: 13
还原数据后,评价模型标准-相对误差绝对值平均MAPE (Mean Absolute Percentage Error):0.090
(5)单位根、协整、格兰杰因果关系
# 单位根检验
# 单位根检验是指检验序列中是否存在单位根,因为存在单位根就是非平稳时间序列了。
# 单位根就是指单位根过程,可以证明,序列中存在单位根过程就不平稳,会使回归分析中存在伪回归
x = diff_adf_test(log_xtrain,zhixindu='5%')
y = diff_adf_test(log_ytrain,zhixindu='5%')
序列1阶平稳,统计量为:-4.2812 ,p值为0.0005, 5%临界值为:-3.3672
序列1阶平稳,统计量为:-4.4592 ,p值为0.0002, 5%临界值为:-3.1894
# 协整检验
print(coint(y,x))
print(coint(x,y))
(-3.499788711567408, 0.03241412320391135, array([-5.04192472, -3.89268694, -3.41677222]))
(-0.141916031919859, 0.9820000262274053, array([-5.04192472, -3.89268694, -3.41677222]))
# 格兰杰因果关系检验
grangercausalitytests(pd.DataFrame([x,y]).T,2)
# 格兰杰因果关系检验
grangercausalitytests(pd.DataFrame([y,x]).T,2)
四、多元回归分析
4.1 可视化北京市GDP与各行业投资额的关系
fig = plt.figure(figsize=(60,50))
for i in range(2,len(names)):
ax = fig.add_subplot(3,5,i-1)
ax.scatter(industry_fac_data[names[i]],industry_gdp_data[names[1]],s=500)
# plt.title(names[i],fontsize=56)
plt.xlabel(names[i]+'投资额',fontsize=48)
plt.ylabel(names[1]+'GDP',fontsize=48)
plt.xticks(fontsize=48)
plt.yticks(fontsize=48)
plt.show()
# 北京市GDP与各行业投资额的相关系数
corr_gdp_industry_list = []
for i in range(1,len(names)):
corr_gdp_industry_list.append(industry_gdp_data[names[1]].corr(industry_fac_data[names[i]]))
# corr_series = pd.Series(corr_gdp_industry_list,index=names[2:len(names)])
figure = plt.figure(figsize=(15,5))
corr_bar = plt.bar(names[1:len(names)],corr_gdp_industry_list)
plt.xticks(rotation=60,fontsize=12)
for bar in corr_bar:
height = bar.get_height()
plt.text(bar.get_x() + bar.get_width() / 2, height, str(('%.2f')%height), ha='center', va='bottom',fontsize=14)
plt.axhline(0.8,color='r')
plt.xticks(fontsize=14)
plt.yticks(fontsize=14)
plt.title('全市GDP与各行业投资额相关性条形图',fontsize=16)
plt.show()
小结:
通过上述北京市GDP和各行业的投资额散点图可知,交通运输仓储和邮政业、信息传输软件和信息技术服务业、房地产业、水利环境和公共设施管理业、教育、卫生和社会工作等6个行业,具有较强的相关性,达到0.8以上。
4.2 多元回归分析全市GDP和行业投资的关系
筛选上述相关性较强的六个行业与全市GDP关系进行回归分析。
#
flag = pd.Series(corr_gdp_industry_list)>0.8
x_name = [names[i] for i in range(2,len(names)) if flag[i-1]]
X = industry_fac_data[x_name]
X = sm.add_constant(X)
Y = industry_gdp_data[names[1]]
model = sm.OLS(Y,X)
model = model.fit()
model.summary()
# industry_gdp_data.index.names
根据上述结果,剔除交通运输仓储和邮政业、房地产业、卫生和社会工作,重新进行拟合。
x_name = ["信息传输、软件和信息技术服务业","水利、环境和公共设施管理业","教育"]
X = industry_fac_data[x_name]
X = sm.add_constant(X)
Y = industry_gdp_data[names[1]]
model = sm.OLS(Y,X)
model = model.fit()
model.summary()
对比未剔除交通运输仓储和邮政业、房地产业、卫生和社会工作的回归模型,剔除后,模型效果更好。
Y_p = model.predict(X)
# 拟合结果可视化
visual_regression_result(range(len(Y)),Y,Y_p)
# visual_regression_result(model,sm.add_constant(xtrain))
fig = plt.figure(figsize=(15,5))
ax = fig.add_subplot(121)
# model.resid.plot.density() #残差密度图
model.resid.hist(bins=5,alpha = 0.5)
model.resid.plot(kind = 'kde', secondary_y=True)
ax.set_title('密度直方图')
# plt.grid()
ax2 = fig.add_subplot(122)
# qq图
stats.probplot(model.resid, dist="norm", plot=plt)
plt.show()
# 残差正态性检验
from scipy.stats import kstest # K-S检验:特点是比较严格,基于的原理是CDF,理论上可以检验任何分布
ks_result = kstest(model.resid,'norm')
print('kstest检验:',ks_result)
from scipy.stats import shapiro # Shapiro检验:专门用来检验正态分布 shapiro 不适合做样本数>5000的正态性检验,检验结果的P值可能不准确
shap_result = shapiro(model.resid)
print('shapiro检验:',shap_result)
from scipy.stats import normaltest # Normal检验:原理是基于数据的skewness和kurtosis
norm_result = normaltest(model.resid,axis=None)
print('normaltest检验:',norm_result)
kstest检验: KstestResult(statistic=0.5714285714285714, pvalue=7.456196123263218e-05)
shapiro检验: (0.9852579236030579, 0.9947238564491272)
normaltest检验: NormaltestResult(statistic=0.3540289636912072, pvalue=0.8377676520133555)
# 定量判断 残差同方差检验
# White's Test
white_test = sm.stats.diagnostic.het_white(model.resid, exog = model.model.exog)
print('模型方差齐性检验统计量:%.2f,P值:%.4f,Fvalue:%.2f,F_pvalue:%.2f:' %(white_test))
# model.model.exog
模型方差齐性检验统计量:6.77,P值:0.6608,Fvalue:0.42,F_pvalue:0.87
print('评价模型标准-相对误差绝对值平均MAPE (Mean Absolute Percentage Error):%.3f'
%(mean_absolute_per_err(Y_p,Y)))
长度: 14
评价模型标准-相对误差绝对值平均MAPE (Mean Absolute Percentage Error):0.031
五、分析函数化Codes
import pandas as pd
import numpy as np
import scipy
import matplotlib.pyplot as plt
import matplotlib as mpl
import seaborn as sns
import statsmodels.api as sm # 最小二乘
from statsmodels.stats.outliers_influence import summary_table # 获得汇总信息
import statsmodels.formula.api as smf
from scipy import stats
from sklearn.metrics import mean_absolute_error
from statsmodels.tsa.stattools import adfuller # ADF检验
from statsmodels.tsa.stattools import coint # 协整检验
from statsmodels.tsa.stattools import grangercausalitytests # 格兰杰因果关系检验
import warnings
warnings.filterwarnings("ignore")# 忽略静态警告
mpl.style.use('seaborn')
# 为了画图中文可以正常显示
plt.rcParams['font.sans-serif'] = ['simhei'] #指定默认字体
plt.rcParams['axes.unicode_minus'] = False #解决保存图像时负号'-'显示为方块的问题
########### 函数定义 区域 ###############################################
def industry_boxplot_mu(data,title_name,sub_ylabel):
'''
title_name: boxplot的title
'''
fig = plt.figure(figsize=(100,60))
plt.title(title_name,fontsize=56)
for i in range(1,len(names)):
ax = fig.add_subplot(2,8,i)
# ax.boxplot(industry_gdp_data[names[i]],
ax.boxplot(data[names[i]],
patch_artist=True, # 要求用自定义颜色填充盒形图,默认白色填充
showmeans=True, # 以点的形式显示均值
boxprops = {'color':'black','facecolor':'#ffffff','linewidth':3}, # 设置箱体属性,填充色和边框色
flierprops = {'marker':'o','markerfacecolor':'red','color':'black','linestyle':'-','linewidth':3}, # 设置异常值属性,点的形状、填充色和边框色
meanprops = {'marker':'D','markerfacecolor':'indianred','linewidth':15}, # 设置均值点的属性,点的形状、填充色
medianprops = {'linestyle':'-','color':'red','linewidth':3}) # 设置中位数线的属性,线的类型和颜色
# plt.title(names[i],fontsize=56)
plt.xlabel(names[i],fontsize=48)
# plt.ylabel(names[i]+'GDP',fontsize=48)
plt.ylabel(names[i]+sub_ylabel,fontsize=48)
plt.xticks(fontsize=48)
plt.yticks(fontsize=48)
plt.show()
'''
可视化行业的历年GDP、历年投资额,以及投资额和GDP的散点图
'''
def gdp_fac_graph_mu(ytrain,xtrain):
'''
ytrain:行业GDP数据
xtrain:行业投资额数据
'''
# industry_GDP = industry_gdp_data[industry_name]
# industry_FAC = industry_fac_data[industry_name]
# 画图
figure = plt.figure(figsize=(20,5))
ax = figure.add_subplot(121)
ax.plot(xtrain.index,xtrain,'rp-',label='投资额')
ax.set_ylabel('投资额')
ax.set_xlabel('年份')
ax.legend(loc=0)
ax = ax.twinx()
ax.plot(ytrain.index,ytrain,'*-',label='GDP')
ax.set_ylabel('GDP')
# ax.set_xlabel('年份')
ax.legend(loc=1)
ax.set_title('时间序列图',fontsize=14)
plt.xticks(fontsize=12)
plt.yticks(fontsize=12)
ax2 = figure.add_subplot(122)
ax2.scatter(xtrain,ytrain,s=50)
plt.title('投资额与GDP关系散点图',fontsize=14)
plt.xlabel('投资额',fontsize=12)
plt.ylabel('GDP',fontsize=12)
plt.xticks(fontsize=12)
plt.yticks(fontsize=12)
plt.show()
'''
对各行业的投资额和GDP,进行一元回归建模
'''
def simple_regression_mu(ytrain,xtrain):
'''
params
ytrain:行业GDP数据
xtrain:行业投资额数据
return
model: 拟合的回归模型
'''
# industry_GDP = industry_gdp_data[industry_name]
# industry_FAC = industry_fac_data[industry_name]
xtrain = sm.add_constant(xtrain) # 线性回归增加常数项 y=kx+b
model = sm.OLS(ytrain, xtrain) # 普通最小二乘模型,ordinary least square model
model = model.fit() #res.model.endog
# 模型检验及系数检验
# print(industry_name+" 的回归模型检验及系数检验结果:\n",model.summary())
y_pre = model.predict(xtrain)
return model,y_pre
# '''
# 对各行业的投资额和GDP取自然对数后,进行一元回归建模
# '''
# def simple_regression_log_mu(ytrain,xtrain):
# '''
# params
# ytrain:行业GDP数据
# xtrain:行业投资额数据
# return
# model: 拟合的回归模型
# '''
# industry_GDP = np.log(industry_gdp_data[industry_name])
# industry_FAC = np.log(industry_fac_data[industry_name])
# industry_FAC = sm.add_constant(industry_FAC) # 线性回归增加常数项 y=kx+b
# model = sm.OLS(industry_GDP, industry_FAC) # 普通最小二乘模型,ordinary least square model
# model = model.fit() #res.model.endog
# # 模型检验及系数检验
# # print(industry_name+" 取自然对数后,回归模型检验及系数检验结果:\n",model.summary())
# return model,industry_FAC
'''
回归结果可视化
'''
def visual_regression_result(xtrain,ytrain,y_pre):
'''
xtrain: 训练数据x
ytrain:训练数据y
y_pre:训练预测值
'''
# ytest =model.predict(xtrain)
#绘制拟合结果和误差图
figure = plt.figure(figsize=(10,5))
plt.scatter(xtrain,ytrain,marker = 'd',color = 'k',label='原始值')
plt.scatter(xtrain,y_pre,marker = 'p',color = 'g',label='预测值')
plt.plot(xtrain,y_pre,color = 'r',label='预测线')
plt.plot([xtrain,xtrain],[ytrain,y_pre] ,color = 'grey')
plt.legend(fontsize = 14)
plt.xticks(fontsize=12)
plt.yticks(fontsize=12)
plt.xlabel("序列",fontsize=12)
plt.ylabel(industry_name+"GDP",fontsize=12)
plt.title(industry_name+'线性回归拟合',fontsize=16)
plt.show()
# '''
# 回归结果可视化
# '''
# def visual_regression_result(xtrain,ytrain,y_pre):
# '''
# xtrain: 训练数据x
# ytrain:训练数据y
# y_pre:训练预测值
# '''
# # ytest =model.predict(xtrain)
# #绘制拟合结果和误差图
# figure = plt.figure(figsize=(12,7))
# plt.scatter(xtrain,ytrain,marker = 'd',color = 'k',label='原始值')
# plt.scatter(xtrain,y_pre,marker = 'p',color = 'g',label='预测值')
# plt.plot(xtrain,y_pre,color = 'r',label='预测线')
# plt.plot([xtrain,xtrain],[ytrain,y_pre],
# color = 'grey')
# plt.legend(fontsize = 14)
# plt.xticks(fontsize=12)
# plt.yticks(fontsize=12)
# plt.xlabel(industry_name+"投资额",fontsize=12)
# plt.ylabel(industry_name+"GDP",fontsize=12)
# plt.title(industry_name+'线性回归拟合',fontsize=16)
# plt.show()
'''
可视化回归后的残差散点图
'''
# def residual_scatter_mu(industry_name,model):
def residual_scatter_mu(model):
'''
industry_name:str,行业名称
model: 拟合的模型
'''
# 残差均值 0
err_mean = np.mean(model.resid)
# 残差标准差
err_std = np.std(model.resid)
# 残差图
figure = plt.figure(figsize=(20,5))
ax = figure.add_subplot(121)
plt.scatter(model.resid.index,model.resid,marker='d',color='k')
plt.plot(model.resid.index,model.resid)
plt.axhline(err_std)
plt.axhline(-err_std)
plt.axhline(0,color='r')
plt.xlabel("年份",fontsize=12)
plt.ylabel("残差",fontsize=12)
plt.title(industry_name+"残差序列图",fontsize=14)
ax2 = figure.add_subplot(122)
plt.scatter(model.resid[:len(model.resid)-1],model.resid[1:len(model.resid)])
plt.xlabel("滞后残差",fontsize=12)
plt.ylabel("残差",fontsize=12)
plt.title("一阶滞后变量的散点图",fontsize=14)
# ax2 = figure.add_subplot(122)
# plt.scatter(industry_gdp_data[industry_name],model.resid)
# plt.axhline(err_std)
# plt.axhline(-err_std)
# plt.xlabel(industry_name+"GDP",fontsize=12)
# plt.ylabel("残差",fontsize=12)
# plt.title(industry_name+"残差散点图",fontsize=14)
plt.show()
'''
相对误差绝对值平均
'''
def mean_absolute_per_err(y_pre,y):
'''
y_pre:预测值
y: 原始数据
'''
result = 0
for i in range(len(y_pre)):
result = result + np.abs((y_pre[i]-y[i])/y[i])
result = result/len(y_pre)
print('长度:',len(y_pre))
return result
'''adfuller()返回值
df : float
Test statistic
pvalue : float
MacKinnon's approximate p-value based on MacKinnon (1994, 2010)
usedlag : int
Number of lags used
nobs : int
Number of observations used for the ADF regression and calculation of
the critical values
critical values : dict
Critical values for the test statistic at the 1 %, 5 %, and 10 %
levels. Based on MacKinnon (2010)
'''
def diff_adf_test(data,max_jieshu=3,zhixindu='5%'):
'''
data:检验序列
max_jieshu:差分的最高阶数
'''
adf_result = adfuller(data)
if adf_result[0] < adf_result[4]['10%']: # 平稳性判断
print('原序列平稳,统计量为:%.4f ,p值为%.4f, %s临界值为:%.4f'%(adf_result[0],adf_result[1],zhixindu,adf_result[4][zhixindu]))
return data
for i in range(1,max_jieshu+1):
temp = data.diff(i)[i:]
adf_result = adfuller(temp)
if adf_result[0] < adf_result[4]['10%']: # 平稳性判断
print('序列%d阶平稳,统计量为:%.4f ,p值为%.4f, %s临界值为:%.4f'%(i,adf_result[0],adf_result[1],zhixindu,adf_result[4][zhixindu]))
return temp
print('原序列在差分%d阶以内,均不平稳'%max_jieshu)
########################################################################
六、题外话
这部分的分析工作用了很长时间,也查看过一些资料,当真正准备把它当一个分析报告想展示的时候,自己突然发现不知道该展示什么,或者说要来说明什么问题。这也是自己第一次尝试分享展示这种分析案例,有很多粗糙的地方和不足,多多练手,多多参考大家的作品,提升自己的实力,并希望能够不断的分享新的有帮助的内容给阅读者。