社区所有版块导航
Python
python开源   Django   Python   DjangoApp   pycharm  
DATA
docker   Elasticsearch  
aigc
aigc   chatgpt  
WEB开发
linux   MongoDB   Redis   DATABASE   NGINX   其他Web框架   web工具   zookeeper   tornado   NoSql   Bootstrap   js   peewee   Git   bottle   IE   MQ   Jquery  
机器学习
机器学习算法  
Python88.com
反馈   公告   社区推广  
产品
短视频  
印度
印度  
Py学习  »  Python

Python私活150元,用随机森林填补缺失值

蚂蚁学Python • 4 年前 • 679 次点击  

众所周知,进行机器学习建模的第一步就是数据预处理,在数据预处理的过程中,处理缺失值则是关键一步。在数据集规模较小的情况下,如果对缺失值进行贸然的删除,则会导致本就不多的数据更为稀少。所以我们需要对缺失值进行一定的填补。

在填补的方法中,有直接用0填补的,有用均值的,有用中位数的,还有用众数的

这些方法虽然简单,但是对数据集的还原程度不高,所以今天为大家介绍如何使用随机森林的方法预测并且填补缺失值

我们先来看看这个数据集

img

它有许多缺失值,我们先对这个数据集进行探索

import numpy as np
import pandas as pd
data = pd.read_csv("test-2.csv")

观察数据

data

yearselling_pricekm_drivenfuelseller_typetransmissionownermileageengineseats
02014450000145500DieselIndividualManualFirst Owner23.401248.05.0
12014370000120000DieselIndividualManualSecond Owner21.141498.05.0
22006158000140000PetrolIndividualManualThird Owner17.701497.05.0
3 2010225000127000DieselIndividualManualFirst Owner23.001396.05.0
42007130000120000PetrolIndividualManualFirst Owner16.101298.05.0
.................................
94200917500055500PetrolDealerManualFirst Owner18.20998.05.0
95201352500061500PetrolDealerManualFirst Owner18.501197.05.0
962016600000150000DieselIndividualManualFirst Owner26.591248.05.0
97201656500072000PetrolDealerAutomaticFirst Owner19.101197.05.0
98200812000068000PetrolDealerManualThird Owner19.70796.05.0

99 rows × 10 columns

data.info()
'pandas.core.frame.DataFrame'>
RangeIndex: 99 entries, 0 to 98
Data columns (total 10 columns):
 #   Column         Non-Null Count  Dtype  
---  ------         --------------  -----  
 0   year           99 non-null     int64  
 1   selling_price  99 non-null     int64  
 2   km_driven      99 non-null     int64  
 3   fuel           99 non-null     object 
 4   seller_type    99 non-null     object 
 5   transmission   99 non-null     object 
 6   owner          99 non-null     object 
 7   mileage        94 non-null     float64
 8   engine         96 non-null     float64
 9   seats          94 non-null     float64
dtypes: float64(3), int64(3), object(4)
memory usage: 7.9+ KB

只有mileage、 engine 、seats有缺失值,其余都完整

重点关注文本数据

data["fuel"].value_counts()
Petrol    48
Diesel    48
LPG        2
CNG        1
Name: fuel, dtype: int64
data["seller_type"].value_counts()
Individual    65
Dealer        34
Name: seller_type, dtype: int64
data["transmission"].value_counts()
Manual       87
Automatic    12
Name: transmission, dtype: int64
data["owner"].value_counts()
First Owner     69
Second Owner    26
Third Owner      4
Name: owner, dtype: int64

对文本数据,一般采用onehot编码或者label编码

从语义上看owner这个属性的值是有明显的定序特征,不宜采用onehot编码,而其余都是分类属性,并且属性值的种类不多

不会对随机森林算法有过度的负面作用,所以可以采用onehot编码

def func(x: str) -> int:
    if x == "First Owner":
        return 1
    elif x == "Second Owner":
        return 2
    elif x == "Third Owner":
        return 3

对owner进行label编码

data["owner"].apply(func)
data["owner"].value_counts()
First Owner     69
Second Owner    26
Third Owner      4
Name: owner, dtype: int64

对其余文本属性,统一使用get_dummies方法进行onehot编码

data = pd.get_dummies(data)
data

yearselling_pricekm_drivenmileageengineseatsfuel_CNGfuel_Dieselfuel_LPGfuel_Petrolseller_type_Dealerseller_type_Individualtransmission_Automatictransmission_Manualowner_First Ownerowner_Second Ownerowner_Third Owner
0201445000014550023.401248.05.0 01000101100
1201437000012000021.141498.05.001000101010
2200615800014000017.701497.05.000010101001
3201022500012700023.001396.05.001000101100
4200713000012000016.101298.05.000010101100
......................................................
9420091750005550018.20998.05.00001100110 0
9520135250006150018.501197.05.000011001100
96201660000015000026.591248.05.001000101100
9720165650007200019.101197.05.000011010100
9820081200006800019.70796.05.000011001001

99 rows × 17 columns

查看编码后的数据

data.info()
'pandas.core.frame.DataFrame'>
RangeIndex: 99 entries, 0 to 98
Data columns (total 17 columns):
 #   Column                  Non-Null Count  Dtype  
---  ------                  --------------  -----  
 0   year                    99 non-null     int64  
 1   selling_price           99 non-null     int64  
 2   km_driven               99 non-null     int64  
 3   mileage                 94 non-null     float64
 4   engine                  96 non-null     float64
 5   seats                   94 non-null     float64
 6   fuel_CNG                99 non-null     uint8  
 7   fuel_Diesel             99 non-null     uint8  
 8   fuel_LPG                99 non-null     uint8  
 9   fuel_Petrol             99 non-null     uint8  
 10  seller_type_Dealer      99 non-null     uint8  
 11  seller_type_Individual  99 non-null     uint8  
 12  transmission_Automatic  99 non-null     uint8  
 13  transmission_Manual     99 non-null     uint8  
 14  owner_First Owner       99 non-null     uint8  
 15  owner_Second Owner      99 non-null     uint8  
 16  owner_Third Owner       99 non-null     uint8  
dtypes: float64(3), int64(3), uint8(11)
memory usage: 5.8 KB

对每一列属性的缺失值个数进行求和统计

data.isnull().sum(axis=0)
year                      0
selling_price             0
km_driven                 0
mileage                   5
engine                    3
seats                     5
fuel_CNG                  0
fuel_Diesel               0
fuel_LPG                  0
fuel_Petrol               0
seller_type_Dealer        0
seller_type_Individual    0
transmission_Automatic    0
transmission_Manual       0
owner_First Owner         0
owner_Second Owner        0
owner_Third Owner         0
dtype: int64

随机森林算法填充缺失值

先填充缺失值较少的的列,之后再填多的

原理:将要填补的列作为目标列,其余列作为属性列,用随机森林预测目标列的值进行填充

用非空的行作为训练集,空的行作为测试集,训练集中的数据有空值,则先用0填充

# 引入随机森林模型和填补缺失值的模型
from sklearn.impute import SimpleImputer
from sklearn.ensemble import RandomForestRegressor

首先去除特定的列得到属性列,记为X;选取特定的列作为目标列,记为Y

在得到的属性列中,用0填补缺失值

在目标列中选取非空的行的index作为选取训练集的依据,空行的index作为测试集的依据

这样就可以在X,Y中得到训练集和测试集了

有了训练集就把它们丢到随机森林训练,然后用训练好的模型预测测试集中的数据得到预测值

最后将预测值填到相应的位置中

for name in ["engine""mileage""seats"]:
    X = data.drop(columns=f"{name}")
    Y = data.loc[:, f"{name}"]
    X_0 = SimpleImputer(missing_values=np.nan, strategy="constant").fit_transform(X)
    y_train = Y[Y.notnull()]
    y_test = Y[Y.isnull()]
    x_train = X_0[y_train.index, :]
    x_test = X_0[y_test.index, :]

    rfc = RandomForestRegressor(n_estimators=100)
    rfc = rfc.fit(x_train, y_train)
    y_predict = rfc.predict(x_test)

    data.loc[Y.isnull(), f"{name}"] = y_predict

查看填充后的数据

data.info()
'pandas.core.frame.DataFrame'>
RangeIndex: 99 entries, 0 to 98
Data columns (total 17 columns):
 #   Column                  Non-Null Count  Dtype  
---  ------                  --------------  -----  
 0   year                    99 non-null     int64  
 1   selling_price           99 non-null     int64  
 2   km_driven               99 non-null     int64  
 3   mileage                 99 non-null     float64
 4   engine                  99 non-null     float64
 5   seats                   99 non-null     float64
 6   fuel_CNG                99 non-null     uint8  
 7   fuel_Diesel             99 non-null     uint8  
 8   fuel_LPG                99 non-null     uint8  
 9   fuel_Petrol             99 non-null     uint8  
 10  seller_type_Dealer      99 non-null     uint8  
 11  seller_type_Individual  99 non-null     uint8  
 12  transmission_Automatic  99 non-null     uint8  
 13  transmission_Manual     99 non-null     uint8  
 14  owner_First Owner       99 non-null     uint8  
 15  owner_Second Owner      99 non-null     uint8  
 16  owner_Third Owner       99 non-null     uint8  
dtypes: float64(3), int64(3), uint8(11)
memory usage: 5.8 KB

可以发现原有的缺失值已经被填好了

最后把结果导出为excel文件

data.to_excel("test-2(填补后).xlsx")


最后,推荐蚂蚁老师的sklearn 100题机器学习课程:

点击阅读原文,也可以到达课程页

Python社区是高质量的Python/Django开发社区
本文地址:http://www.python88.com/topic/125699