使用随机森林回归来填补缺失值
1.导包
先导入一些需要的包
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.datasets import load_boston
from sklearn.impute import SimpleImputer#用于填补缺少的类
from sklearn.ensemble import RandomForestRegressor
2.导入数据
dataset = load_boston()
Ⅰ.简单数据探索
dataset.data
dataset.target
dataset.info() wrong for dataFrame
dataset.data.shape
Ⅱ.强行制造缺失的数据
在制造之前我们要保留一个完整的数据集
X_full,y_full = dataset.data,dataset.target#没有缺失数字的数据集
以完整的形状来进行填补的操作
n_samples = X_full.shape[0]
n_samples
n_features = X_full.shape[1]
n_features#13
Ⅲ.为完整数据集放入缺失值
确定一种随机种子,一种随机模式,代替下面所有可能使用random_state的地方
rng = np.random.RandomState(0)
首先我们确定放入的缺少数据的比例,这里就假设50%
missing_rate = 0.5
506 * 13 * 0.5
np.floor表示向下取整,返回.0格式的浮点数。
为什么要先int呢–>如果更改成其他的比例可能是小数
n_missing_samples = int(np.floor(n_samples*n_features*missing_rate))
print(n_missing_samples)
所有数据要随机遍布在数据集的各行各列当中,而一个缺失的数据会需要一个行索引和一个列索引,
如果能够创造一个数组,包含3289个分布在0~ 506中间的行索引,和3289个分布在0~13之间的列索引,
那我们就可以利用索引来为数据中的任意3289个位置赋空值,
然后我们用0,均值和随机森林来填写这些缺失值,然后查看回归的结果如何。
randint(上限,下限,n)请在上下限之间取出n个整数
missing_features = rng.randint(0,n_features,n_missing_samples)#[0,13)
missing_samples = rng.randint(0,n_samples,n_missing_samples)#[0,506)
X_missing = X_full.copy()
y_use = y_full.copy()#这里是不会变的、监督学习
把之前取好的3289个缺失位置的xy对应(x,y)在数组中取空
X_missing[missing_samples,missing_features] = np.nan
变成DataFrame的格式
X_missing = pd.DataFrame(X_missing)
X_missing
Ⅳ、使用零和均值填补缺少值
查看所有没有缺失的值
(1)使用均值
from sklearn.impute import SimpleImputer
imp_mean = SimpleImputer(missing_values=np.nan,strategy="mean")#SimpleImputer的实例化
X_missing_mean = imp_mean.fit_transform(X_missing)#训练fit+导出predict--->特殊的接口~fit_transform
X_missing_mean
isnull–>dataFrame才能用
pd.DataFrame(X_missing_mean).isnull()#有null返回true
看不清所有
pd.DataFrame(X_missing_mean).isnull().sum()
(2)使用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_mean).isnull().sum()
(3)使用随机森林填补缺失值
任何回归都是从特征矩阵中学习,然后求解连续型标签y的过程。
之所以这个合理是因为回归算法认为特征矩阵和标签之间存在着某种联系。
这个联系也导致标签和特征是可以相互转换的。
“地区、环境、是否学区”<——>“房价”是可以相互转换一样。
回归填补缺失值,正是利用了这种思想。
对于一个有n个特征来说
特征T缺失->把T当作label~y
缺失的部分当做y_test,有的部分当作y_train.
同时把其他n-1个特征和原来的标签当作X,并且按照y是否缺失分为X_train 和 X_test
这种做法,对于某一个特征大量缺失,其他特征却很完整的情况,非常适用。
当然有其他缺失值也很正常,
遍历所有的特征,从缺失最少的开始进行填补。
填补一个特征时,先将其他特征的缺失值用0代替,每完成一次回归预测,就将预测值放到原本的特征矩阵中,再继续填 补下一个特征。
每一次填补完毕,有缺失值的特征会减少一个,所以每次循环后,需要用0来填补的特征就越来越少。
以第六列为例
X_missing_reg = X_missing.copy()
sortindex = np.argsort(X_missing_reg.isnull().sum(axis=0)).values
sortindex
X_missing_reg.head()
避免X_missing_ reg被覆盖
df = X_missing_ref
取所有行和第六列
fillc = df.iloc[:,6]
fillc
除了第六列都取出来再加上原来的标签
df.columns != 6
df.iloc[:,df.columns != 6]
第一个参数[]包含所有要连接的部分,axis=1表示横向。
不要重复按,会覆盖df
df = pd.concat([df.iloc[:,df.columns != 6],pd.DataFrame(y_full)],axis=1)
实例化和接口同时进行
df=SimpleImputer(missing_values=np.nan,strategy='constant',fill_value=0).fit_transform(df)
pd.DataFrame(df)
pd.DataFrame(df_0).isnull().sum()
ytrain = fillc[fillc.notnull()]
ytest = fillc[fillc.isnull()]
我们需要的是ytest是空的,我们需要的是,其所带的索引来定位xtest
ytest
ytrain.index
Xtrain = df_0[ytrain.index,:]#以行取索引,列取全部
pd.DataFrame(Xtrain)
Xtest = df_0[ytest.index,:]
pd.DataFrame(Xtest)
用随机森林来填补缺失值
rfc = RandomForestRegressor(n_estimators=100)
rfc = rfc.fit(Xtrain,ytrain)
ypred = rfc.predict(Xtest)
将填补好的特征返回到我们的原始的特殊矩阵中
X_missing_reg.loc[X_missing_reg.iloc[:,6].isnull(),6] = ypred