python实现-用随机森林填补缺失值、均值填充0填充的比较

sklearn中,可以使用sklearn.impute.SimpleImputer来轻松地填充均值等

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt

from sklearn.datasets import load_boston  #波士顿数据
from sklearn.impute import SimpleImputer  #填补缺失值的类:sklearn.impute.SimpleImputer
from sklearn.ensemble import RandomForestRegressor  #随机森林
from sklearn.model_selection import cross_val_score  #交叉验证
dataset = load_boston()
dataset.data.shape
dataset #可以查看数据集
dataset.target #标签不是分类,是回归
#总共506*13=6578个数据
X_full, y_full = dataset.data, dataset.target  #完整数据--先变缺失
n_samples = X_full.shape[0]
n_features = X_full.shape[1]
#首先确定我们希望放入的缺失数据的比例,在这里我们假设是50%,那总共就要有3289个数据缺失

rng = np.random.RandomState(0)
missing_rate = 0.5
n_missing_samples = int(np.floor(n_samples * n_features * missing_rate))
#np.floor向下取整,返回.0格式的浮点数
n_missing_samples #设定要缺失的数据量

所有数据要随机遍布在数据集的各行各列当中,而一个缺失的数据会需要一个行索引和一个列索引
如果能够创造一个数组,包含3289个分布在0506中间的行索引,和3289个分布在013之间的列索引,
那我们就可以利用索引来为数据中的任意3289个位置赋空值
然后我们用0,均值和随机森林来填写这些缺失值,然后查看回归的结果如何

#randint(下限,上限,n)在下限与上限之间随机取出n个整数
missing_features = rng.randint(0,n_features,n_missing_samples)
missing_samples = rng.randint(0,n_samples,n_missing_samples)
#分别取了行索引与列索引个随机数

missing_samples =rng.choice(dataset.data.shape[0],n_missing_samples,replace=False)
我们现在采样了3289个数据,远远超过我们的样本量506,所以我们使用随机抽取的函数randint。
但如果我们需要的数据量小于我们的样本量506,那我们可以采用np.random.choice来抽样,choice会随机抽取不重复的随机数,
因此可以帮助我们让数据更加分散,确保数据不会集中在一些行中

X_missing = X_full.copy()
y_missing = y_full.copy()#复制一下,保存之前的完整数据

X_missing[missing_samples,missing_features] = np.nan
X_missing = pd.DataFrame(X_missing)
#转换成DataFrame是为了后续方便各种操作,
#numpy对矩阵的运算速度快到拯救人生,但是在索引等功能上却不如pandas来得好用
X_missing
#特征值间可以有缺失,但y属性列是不应该有缺失的,否则是无监督
#SimpleImputer使用均值mean进行填补
from sklearn.impute import SimpleImputer
imp_mean = SimpleImputer(missing_values=np.nan, strategy='mean')#实例化
X_missing_mean = imp_mean.fit_transform(X_missing) 
#训练fit+导出predict >>>fit_transform
#X_missing_mean 是已经填充完的数据
pd.DataFrame(X_missing_mean).isnull().sum() 
#检查是否有空值xx.isnull().sum()--xx要是DataFrame
#使用0进行填补
imp_0 = SimpleImputer(missing_values=np.nan, strategy="constant",fill_value=0)
X_missing_0 = imp_0.fit_transform(X_missing)
pd.DataFrame(X_missing_0).isnull().sum() 

使用随机森林回归填充缺失值
先填补缺失少的列,填补一个特征时,先将其他列缺失用0替代,完成回归预测,将预测值放到原特征列中。循环下去

X_missing_reg = X_missing.copy()
sortindex = np.argsort(X_missing_reg.isnull().sum(axis=0)).values
#对缺失值从少到多填充,所以先对缺失数量排序
#sum(axis=0)对列求和
sortindex

np.argsort(X_missing_reg.isnull().sum(axis=0))
#相比np.sort带着有索引
#从小到大排序的顺序所对应的索引

np.sort(X_missing_reg.isnull().sum(axis=0))
for i in sortindex:
    #构建我们的新特征矩阵和新标签
    df = X_missing_reg
    fillc = df.iloc[:,i]
    df = pd.concat([df.iloc[:,df.columns != i],pd.DataFrame(y_full)],axis=1)
    
    #在新特征矩阵中,对含有缺失值的列,进行0的填补
    df_0 =SimpleImputer(missing_values=np.nan,strategy='constant',fill_value=0).fit_transform(df)
    
    #找出我们的训练集和测试集
    Ytrain = fillc[fillc.notnull()]
    Ytest = fillc[fillc.isnull()]
    Xtrain = df_0[Ytrain.index,:]
    Xtest = df_0[Ytest.index,:]
    
    #用随机森林回归来填补缺失值
    rfc = RandomForestRegressor(n_estimators=100)
    rfc = rfc.fit(Xtrain, Ytrain)
    Ypredict = rfc.predict(Xtest)
    
    #将填补好的特征返回到我们的原始的特征矩阵中
    X_missing_reg.loc[X_missing_reg.iloc[:,i].isnull(),i] = Ypredict
    

下面部分是理解for循环里面的代码

#构建新特征矩阵(没有被选择去填充的特征+原始标签)和新标签(被选中去填充的特征)
df = X_missing_reg  #复制了一下,方便下次循环
fillc = df.iloc[:,6]   #新标签,按照sortindex中的索引序列
df = pd.concat([df.iloc[:,df.columns != 6],pd.DataFrame(y_full)],axis=1) #新特征矩阵
#新特征列:除了取出的标签列后的数据列+原标签列
#变成DataFrame后concat([要连接的数据a,b],axis=1) ---axis=1指按照列连接

#在新特征矩阵中,对含有缺失值的列,进行0的填补
#SimpleImputer(missing_values=np.nan,strategy='constant',fill_value=0)前半部分实例化,fit_transform训练
df_0 =SimpleImputer(missing_values=np.nan,strategy='constant',fill_value=0).fit_transform(df)
#pd.DataFrame(df_0).isnull().sum() #检查一下是否填充完成

#找出我们的训练集和测试集

#Ytrain是被选择要填充的特征(即当前标签列)中,存在的值(非空值)
Ytrain = fillc[fillc.notnull()]
#Ytest是被选中的要填充的特征(即当前标签列)中,不存在的值(空值)
#需要的不是Ytest的值,是要Ytest所带的索引
Ytest = fillc[fillc.isnull()]

#新特征矩阵上,被选出来的要填充的那个特征非空值所对应的记录
Xtrain = df_0[Ytrain.index,:]
#新特征矩阵上,被选出来的要填充的那个特征空值所对应的记录
Xtest = df_0[Ytest.index,:]

#用随机森林回归来填补缺失值
rfc = RandomForestRegressor(n_estimators=100) #实例化
rfc = rfc.fit(Xtrain, Ytrain)  #导入训练集训练
Ypredict = rfc.predict(Xtest)   #预测结果,被我们用来填补空值的这些值

#将填补好的特征返回到我们的原始的特征矩阵中
X_missing_reg.loc[X_missing_reg.iloc[:,6].isnull(),6] = Ypredict
#第6列是空值的行+第六列--进行填充

#X_missing_reg  #完成了第六列的填充
#X_missing_reg.isnull().sum()

继续

X_missing_reg  #查看
X_missing_reg.isnull().sum()  #填充完了

#四组数据:均值填充、0填充、随机森林填充、原完整数据
#对比看预测效果

X = [X_full,X_missing_mean,X_missing_0,X_missing_reg]

mse = []
std = []
for x in X:
    estimator = RandomForestRegressor(random_state=0, n_estimators=100) #实例化
    scores = cross_val_score(estimator,x,y_full,scoring='neg_mean_squared_error', cv=5).mean() 
    #交叉验证打分,回归打分-负的均方误差
    mse.append(scores * -1) #打分储存在mse中

mse #mse越小越好
[*zip(['X_full','X_missing_mean','X_missing_0','X_missing_reg'],mse)]
#用zip把名称与分数连起来,[]列表打开
#回归的mse甚至比原数据还低

作图展示

x_labels = ['Full data','Zero Imputation','Mean Imputation','Regressor Imputation']

colors = ['r', 'g', 'b', 'orange']

plt.figure(figsize=(12, 6)) #画布
ax = plt.subplot(111)     #plt.subplot添加子图,定义图表位置第一行第一列第一个表
for i in np.arange(len(mse)):
    ax.barh(i, mse[i],color=colors[i], alpha=0.6, align='center')
#barh横向条形图
ax.set_title('Imputation Techniques with Boston Data') #波士顿在不同填充技术下的表现
ax.set_xlim(left=np.min(mse) * 0.9,right=np.max(mse) * 1.1)
ax.set_yticks(np.arange(len(mse)))
ax.set_xlabel('MSE')
ax.set_yticklabels(x_labels)
plt.show()
#横坐标mse,纵坐标各种填充方法

python实现-用随机森林填补缺失值、均值填充0填充的比较_第1张图片

你可能感兴趣的:(数据挖掘,python,随机森林,均值算法)