数据分析流
数据: 残耗.xlsx
注意:数据中的字段的名字以v开头的都不是连续形变量,是分类形变量

导入包
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import statsmodels.formula.api as smf
from sklearn import linear_model
import seaborn as sns
%matplotlib inline
plt.rcParams["font.sans-serif"]=["SimHei"]
plt.rcParams["axes.unicode_minus"]=False
第1,2,3步,确定需求、y、x都是根据理论确定
第4步
描述数据——获取每个变量的分布形态、均值、中位数、最大值、最小值等常用指标
data = pd.read_excel(r"D:\个人文档\Python统计\python统计分析课件20200513\data\残耗.xlsx")
data.head(2) # 查看请两行数据
data.iloc[:,1:].hist(figsize=(20,16)) # 获取分布形态
data.lioc[:,1:].describe() # 获取均值、中位数、最大值、最小值等常用指标
第5步
5.1处理缺失值
60%以上的缺失,分类法处理或删除,其他中位数填补
data.isnull().sum()/data.shape[0] # 查看每一个字段的缺失值比例
# 使用中位数填补(方式一)
"""
data51 = data.fillna(value=data.median()) #中位数填补(中位数模型77.5%,随机森林79.2%)
"""
# 使用模型填补(方式二: 随机森林)
from missingpy import KNNImputer,MissForest
imput = MissForest(n_estimators=2,min_samples_leaf=9000,n_jobs=-1,copy=False)
data5 = imput.fit_transform(data.iloc[:,1:])
# data5是numpy的array类型,转化成DataFrame
data51 = pd.DataFrame(data5,columns=data.iloc[:,1:].columns)
#data51.info()
x,y = data51.iloc[:,1:],data51["v残耗"]
reg = linear_model.LinearRegression()
reg.fit(x,y) # 拟合数据
reg.score(x,y) # 0.7907786028930843,预测成功的概率约百分之79
补充: 1.关于missingpy包的安装以及导入:
如果在终端安装 pip3 install missingpy,在Pycharm中能用,但是报错,必须加上下面3行代码
import sklearn.neighbors._base
import sys
sys.modules['sklearn.neighbors.base'] = sklearn.neighbors._base
而在jupyter中,出现了missingpy模块找不到的错误,而解决办法是在jupyter的代码块上输入:
! pip3 install missingpy # 在这个jupyter上重新安装一次,就解决问题啦
2.关于MissForest中的参数
-
n_estimators :int 关于随机森林中的树的个数
-
min_samples :int 关于随机森林中叶子的个数
-
n_jobs :int 用几个核并行执行这个算法,-1代表调用计算机上的所有资源
-
copy: bool 不复制
5.2异常值---强异常值的处理(模型83%)
# 5.2异常值---强异常值的处理(模型83%)
var=[(-0.01,'lHH',140000),(-0.01,'偏离位',10000),(0,'助燃',100),(-0.01,'助燃反应',2000),
(-0.01,'助燃柠檬',10000),(20,'助燃添加',29.7),(0,'助燃点',1000),(-0.01,'吸阻',1000),
(10,'吸阻过滤',129),(0,'噪声',100),(-10000,'圆周点位',29.7),(-0.01,'撤回点位',1000),
(0,'收紧度',1000),(0,'标注',129),(0,'检查点位',100),(-0.01,'气体综合',10000),
(0,'消耗烟脂',500),(-200,'温控',200),(-0.01,'烟碱HW',2000),(-0.01,'烟碱量',10000),
(0,'焦油量',200),(-0.01,'起点位',1000),(-0.01,'过滤时效',1500),(30,'通路',40),
(-10000,'钠元素',500),(20,'钾元素',100)
]
for (t,i,j) in var:
data51[i+str("01")]=np.where(data51[i]>=j,j,
np.where(data51[i]<=t,t,data51[i].copy()))
# print(data51[i+str("01")].describe())
data52=data51.iloc[:,[*range(0,6),*range(32,58)]]
# data52.info()
x,y=data52.iloc[:,2:],data52['v残耗']
# iloc[:,2:],取了第三列以后的数据作为x,是因为样品序列字段不重要,只是一个序列数字,没什么可拟合性
reg=linear_model.LinearRegression().fit(x,y)
reg.score(x,y) # 0.8270159704827226 预测成功的概率约百分之83
5.3 特征筛选(Filter过滤法)--业务上不重要的
from sklearn.feature_selection import SelectKBest,SelectPercentile,f_regression
# 本次筛选用 SelectPercentile,f_regression
x,y = data52.iloc[:,2:],data52["v残耗"]
fit = SelectPercentile(score_func=f_regression,percentile=70)# 建议去除30%
fit.fit_transform(x,y) # 拟合 + 转换(保留了显著性在前百分之70的字段)
# 合并数据
data53 = pd.concat([data52["v残耗"],x.iloc[:,fit.get_support(indices=True)]],axis=1)
"""
fit.get_support() 返回一个bool数组,如果字段的显著性在前百分之70,则为True,否则False
加上indices=True,将会返回一个显著性在前百分之70的字段的序列
"""
5.4 共线性--严重共线性0.9以上,合并或删除
-
df.corr(),求R方
d = data53.corr()
d[d<=0.9] = 0.01 # 赋值显示高相关的变量,更容易观察
# 绘图
sns.heatmap(d)
# 再次检查
print([data53['气体综合01'].corr(data53['烟碱量01']),data53['过滤时效01'].corr(data53['v3燃料类型'])])
# [0.9801723413278989, 0.9157417299234101]
# 再次通过绘图观察
# plt.scatter(data53["v3燃料类型"],data53["过滤时效01"]) # 删除过滤时效01,在业务上不重要
# plt.scatter(data53["气体综合01"],data53["烟碱量01"])
# plt.show()
#拟合线性形式的模型
from scipy.optimize import curve_fit
# 拟合一个函数(线性)
def f(x,b0,b1):
return b0+b1*x
popt,pcov = curve_fit(f,data53["烟碱量01"],data53["气体综合01"])
b0 = popt[0]
b1 = popt[1]
data53["成分烟碱"] = b0+b1*data53["烟碱量01"] # 拟合
# 计算R方,如果与y的相关高于单个x与y的相关则保留;
print("R方:-->",data53["成分烟碱"].corr(data53["烟碱量01"]))
# R方: 0.9999999999999994(保留)
# 删除
data54 = data53.drop(["气体综合01","烟碱量01","过滤时效01"],axis=1)
# 查看字段总个数:
data54.shape[1] # 20
# 跑一下预测成功的概率
x,y=data54.iloc[:,1:],data54['v残耗']
reg=linear_model.LinearRegression()
reg.fit(x,y)
reg.score(x,y) # 0.826282754943141
补充:
该函数是实现合并两个字段的模型
例:
def f(x,b0,b1):return b0+b1*x1
#--------------函数及图形---------------------------
# plt.subplots(2,3,figsize=(16,8));b0=1;b1=2;
# plt.subplot(231);x=np.random.randint(-5,5,100);y=1/(1+np.exp((-b0-b1*x)))
# plt.scatter(x,y,label='logistic');plt.legend()
# plt.subplot(232);b0=5;b1=2;x=np.random.randint(0,100,100);y=b0 + (b1 * np.log(x))
# plt.scatter(x,y,label='对数');plt.legend()
# plt.subplot(233);b0=5;b1=2;x=np.random.randint(0,10,100);y=b0 * (np.exp((b1 * x)))
# plt.scatter(x,y,label='指数');plt.legend()
# plt.subplot(234);b0=5;b1=2;x=np.random.randint(0,10,100);y=b0 + (b1 / x)
# plt.scatter(x,y,label='逆');plt.legend()
# plt.subplot(235);b0=5;b1=2;x=np.random.randint(0,10,100);y=b0 * (x**b1)
# plt.scatter(x,y,label='幂');plt.legend()
# plt.subplot(236);b0=5;b1=2;x=np.random.randint(-100,100,100);y=np.exp(b0 + (b1/x))
# plt.scatter(x,y,label='S 曲线');plt.legend()
画图预测
x,y = data54.iloc[:,1:],data54["v残耗"]
reg = linear_model.LinearRegression()
reg.fit(x,y)
reg.score(x,y)
# reg.predict(x) y的估计值
# 残差: y-y的估计值
# 标准化残差: (残差-残差的均值)/残差的标准差
# 思路: 1. 画一个y和y的估计值的散点图
# 2. 画一个y的估计值和残差的残差图
plt.subplots(1,2,figsize=(12,8))
plt.subplot(121)
r2 = reg.score(x,y)
plt.plot(y,reg.predict(x),'o',label=r2) # 画一个y和y的估计值的散点图
print(r2)
# 计算残差resid
resid = y-reg.predict(x)
# 计算标准化残差
std_resid = (resid-np.mean(resid))/np.std(resid)
std_resid
plt.subplot(122)
plt.plot(reg.predict(x),std_resid,'o',label="残差图")
# 显示图例
plt.legend()
# 一个好的残差图的看法:
# - 0上下随机分布
# - 幅度一样
# - 不能出现形状
5.5 变量变换-----关注y是否需要变换
data54['v残耗log']=np.log(data54['v残耗'])
本案例中无需变换
5.6 编码-----消除异常值、分组(标签化)
data53['烟碱量02']=pd.qcut(data53['烟碱量01'],q=4)
本案例中无需变换
5.2+ 异常值---多变量异常值处理
#5.2+ 异常值---多变量异常值处理
data54["标准化残差"] = std_resid
data54.shape # (56760, 21)
data54_99 = data54[np.abs(data54["标准化残差"])<=6] # 删除异常值
data54_2 = data54_99.drop(["标准化残差"],axis=1)
data54_2.shape # (56597, 20)
# 在5.2+中,建议删除的异常值为总数的1%
# 再次模型预测R2
x,y = data54_2.iloc[:,1:],data54_2["v残耗"]
reg = linear_model.LinearRegression()
reg.fit(x,y)
reg.score(x,y) # 0.8564624636967353
5.3+ 特征筛选(Wrapper包装法RFE;Embedded嵌入法SelectFromModel)
#5.3+ 特征筛选(Wrapper包装法RFE;Embedded嵌入法SelectFromModel)
from sklearn.feature_selection import RFE,SelectFromModel
from sklearn.ensemble import RandomForestRegressor
from sklearn.svm import LinearSVR
x54_1,y54_1 = data54_2.iloc[:,1:],data54_2["v残耗"]
# rfr = RandomForestRegressor(n_estimators=10,min_samples_leaf=10000)
# selector=RFE(rfr,n_features_to_select=5).fit(x54_1,y54_1)
# feature_selection=5 选择最好的5个变量
data55 = pd.concat([data54_2["v残耗"],data54_2[data54_2.columns[selector.get_support(indices=True)]]],axis=1)
data55
x,y = data55.iloc[:,1:],data55["v残耗"]
reg = linear_model.LinearRegression()
reg.fit(x,y)
reg.score(x,y)
浙公网安备 33010602011771号