pandas用众数填充缺失值_【机器学习】scikit-learn中的数据预处理小结(归一化、缺失值填充、离散特征编码、连续值分箱)...

一.概述

1. 数据预处理

数据预处理是从数据中检测,修改或删除不准确或不适用于模型的记录的过程

可能面对的问题有:数据类型不同,比如有的是文字,有的是数字,有的含时间序列,有的连续,有的间断。 也可能,数据的质量不行,有噪声,有异常,有缺失,数据出错,量纲不一,有重复,数据是偏态,数据量太大或太小 。

数据预处理的目的:让数据适应模型,匹配模型的需求 。

2.sklearn中的数据预处理

sklearn中包含众多数据预处理相关的模块,包括:

模块preprocessing:几乎包含数据预处理的所有内容

模块Impute:填补缺失值专用

二 . 数据预处理

1.归一化

在机器学习算法实践中,我们往往有着将不同规格的数据转换到同一规格,或不同分布的数据转换到某个特定分布 的需求,这种需求统称为将数据“无量纲化”。

譬如梯度和矩阵为核心的算法中,譬如逻辑回归,支持向量机,神经 网络,无量纲化可以加快求解速度;而在距离类模型,譬如K近邻,K-Means聚类中,无量纲化可以帮我们提升模型精度,避免某一个取值范围特别大的特征对距离计算造成影响。

(1)preprocessing.MinMaxScaler

当数据(x)按照最小值中心化后,再按极差(最大值 - 最小值)缩放,数据移动了最小值个单位,并且会被收敛到 [0,1]之间,而这个过程,就叫做数据归一化(Normalization,又称Min-Max Scaling)。

归一化之后的数据服从正态分 布,公式如下:

\[x^{*} = \frac{x-min(x)}{max(x)-min(x)}

\]

在sklearn当中,我们使用preprocessing.MinMaxScaler来实现这个功能。

MinMaxScaler有一个重要参数, feature_range,控制我们希望把数据压缩到的范围,默认是[0,1].

from sklearn.preprocessing import MinMaxScaler

data = [[-1, 2], [-0.5, 6], [0, 10], [1, 18]]

#实现归一化

scaler = MinMaxScaler(feature_range=[5,10]) #实例化,feature_range默认是[0,1]

# scaler = scaler.fit(data) #fit,在这里本质是生成min(x)和max(x)

# result = scaler.transform(data) #通过接口导出结果 result

result_ = scaler.fit_transform(data) #训练和导出结果一步达成,可以替代上两行数据

result_

array([[ 5. , 5. ],

[ 6.25, 6.25],

[ 7.5 , 7.5 ],

[10. , 10. ]])

(2) preprocessing.StandardScale

当数据(x)按均值(μ)中心化后,再按标准差(σ)缩放,数据就会服从为均值为0,方差为1的正态分布(即标准正态分 布),而这个过程,就叫做数据标准化(Standardization,又称Z-score normalization),公式如下:

\[x^{*} = \frac{x-μ}{σ}

\]

from sklearn.preprocessing import StandardScaler

data = [[-1, 2], [-0.5, 6], [0, 10], [1, 18]]

scaler = StandardScaler() #实例化

# scaler = scaler.fit(data) #fit,本质是生成均值和方差

# result = scaler.transform(data) #通过接口导出结果

result_ = scaler.fit_transform(data) #使用fit_transform(data)一步达成结果

result_

array([[-1.18321596, -1.18321596],

[-0.50709255, -0.50709255],

[ 0.16903085, 0.16903085],

[ 1.52127766, 1.52127766]])

(3) StandardScaler和MinMaxScaler选哪个?

看情况。大多数机器学习算法中,会选择StandardScaler来进行特征缩放,因为MinMaxScaler对异常值非常敏 感。在PCA,聚类,逻辑回归,支持向量机,神经网络这些算法中,StandardScaler往往是最好的选择。

MinMaxScaler在不涉及距离度量、梯度、协方差计算以及数据需要被压缩到特定区间时使用广泛,比如数字图像 处理中量化像素强度时,都会使用MinMaxScaler将数据压缩于[0,1]区间之中。

2.缺失值

数据预处理中非常重要的一项就是处理缺失值。

对于连续值,常常使用均值或者中位数去填充缺失值;

对于离散值,常常使用众数填充,或者把缺失值当作一个单独的类别。

对于缺失率超过一定阈值的特征,可以考虑直接舍弃。

import pandas as pd

data = pd.read_csv(r"./../Narrativedata.csv",index_col=0)

data.info()

Int64Index: 891 entries, 0 to 890

Data columns (total 4 columns):

Age 714 non-null float64

Sex 891 non-null object

Embarked 889 non-null object

Survived 891 non-null object

dtypes: float64(1), object(3)

memory usage: 34.8+ KB

以Titanic数据为例,可以看到其中Age和Embarked两列有缺失值,且分别为连续值和离散值。

(1) impute.SimpleImputer

8e401235ac7ce5d3c5ba3f115967dd47.png

from sklearn.impute import SimpleImputer

# 对连续值Age进行填充

Age = data.loc[:,"Age"].values.reshape(-1,1) #sklearn当中特征矩阵必须是二维

# 实例化

age_median = SimpleImputer(strategy="median") #用中位数填补 (默认均值填补)

age_0 = SimpleImputer(strategy="constant",fill_value=0) #使用具体值填补,用fill_value指定

# 转化

age_median = age_median.fit_transform(Age) #fit_transform一步完成调取结果

age_0 = age_0.fit_transform(Age)

#把填补后的列赋值回原来的矩阵里

data.loc[:,"Age"] = age_median

data.info()

Int64Index: 891 entries, 0 to 890

Data columns (total 4 columns):

Age 891 non-null float64

Sex 891 non-null object

Embarked 889 non-null object

Survived 891 non-null object

dtypes: float64(1), object(3)

memory usage: 34.8+ KB

# 对离散值Embarked进行填充

Embarked = data.loc[:,"Embarked"].values.reshape(-1,1)

Embarked_most = SimpleImputer(strategy = "most_frequent") #使用众数填补

data.loc[:,"Embarked"] = Embarked_most.fit_transform(Embarked)

data.info()

Int64Index: 891 entries, 0 to 890

Data columns (total 4 columns):

Age 891 non-null float64

Sex 891 non-null object

Embarked 891 non-null object

Survived 891 non-null object

dtypes: float64(1), object(3)

memory usage: 34.8+ KB

(2) 用Pandas和Numpy进行填补

pd.fillna() 使用特定的值填充

pd.dropna(axis=0)删除所有有缺失值的行/列

import pandas as pd

data1 = pd.read_csv(r"./../Narrativedata.csv",index_col=0)

data1.loc[:,"Age"] = data1.loc[:,"Age"].fillna(data1.loc[:,"Age"].median()) #.fillna 在data1Frame里面直接进行填补

data1.dropna(axis=0,inplace=True) #.dropna(axis=0)删除所有有缺失值的行,.dropna(axis=1)删除所有有缺失值的列

data1.info()

Int64Index: 889 entries, 0 to 890

Data columns (total 4 columns):

Age 889 non-null float64

Sex 889 non-null object

Embarked 889 non-null object

Survived 889 non-null object

dtypes: float64(1), object(3)

memory usage: 34.7+ KB

3.处理离散特征:编码和哑变量

在sklearn当中,除了专用来处理文字的算法,其他算法在fit的时候全部要求输入数组或矩阵,也不能够导 入文字型数据。

为了让数据适 应算法和库,我们必须将数据进行编码,即是说,将文字型数据转换为数值型。

(1) preprocessing.LabelEncoder:标签专用,能够将分类转换为分类数值

from sklearn.preprocessing import LabelEncoder

y = data.iloc[:,-1] #要输入的是标签,不是特征矩阵,所以允许一维

print(y[:10])

le = LabelEncoder() #实例化

label = le.fit_transform(y) # 匹配加转化一步到位

# le = le.fit(y)

# label = le.transform(y)

print(label[:10])

print(le.classes_) # 查看有多少类

data.iloc[:,-1] =label

0 No

1 Yes

2 Yes

3 Yes

4 No

5 No

6 No

7 No

8 Yes

9 Yes

Name: Survived, dtype: object

[0 2 2 2 0 0 0 0 2 2]

['No' 'Unknown' 'Yes']

(2)preprocessing.OrdinalEncoder:特征专用,能够将分类特征转换为分类数 (一般用于有序变量)

data_ =data.copy()

# 观察特征的原样式

data_.iloc[:,1:-1][:10]

Sex

Embarked

0

male

S

1

female

C

2

female

S

3

female

S

4

male

S

5

male

Q

6

male

S

7

male

S

8

female

S

9

female

C

from sklearn.preprocessing import OrdinalEncoder

# 类似的,把实例化,匹配,转化和赋值写在一条语句上

data_.iloc[:,1:-1] = OrdinalEncoder().fit_transform(data_.iloc[:,1:-1])

#接口categories_对应LabelEncoder的接口classes_,一模一样的功能

print(OrdinalEncoder().fit(data_.iloc[:,1:-1]).categories_)

#查看数据,

data_.head()

[array([0., 1.]), array([0., 1., 2.])]

Age

Sex

Embarked

Survived

0

22.0

1.0

2.0

0

1

38.0

0.0

0.0

2

2

26.0

0.0

2.0

2

3

35.0

0.0

2.0

2

4

35.0

1.0

2.0

0

data_.info()

Int64Index: 891 entries, 0 to 890

Data columns (total 4 columns):

Age 891 non-null float64

Sex 891 non-null float64

Embarked 891 non-null float64

Survived 891 non-null int32

dtypes: float64(3), int32(1)

memory usage: 31.3 KB

由以上的数据情况可以看出,Age和Embarked的缺失值已被填充,特征Sex和Embarked等分类特征已转化为分类数值,标签Survived也已转化为分类数值。

(3) preprocessing.OneHotEncoder:独热编码,创建哑变量

由上面的处理可以看到OrdinalEncoder会把类别变量变成数值,比如转化为[0,1,2],这三个数字在算法看来,是连续且可以计算的,可能有大小并且有着可以相加相乘的联系。但是有的类别变量各类别是独立的,如果转化成数值会给算法传达了一些不准确的信息,而这会影响我们的建模。

因此,类别OrdinalEncoder可以用来处理有序变量,但对于名义变量,我们只有使用独热编码,以哑变量的方式来处理,才能够尽量 向算法传达最准确的信息。

# 同样的,观察下原数据样式

data.iloc[:,1:-1][:10]

Sex

Embarked

0

male

S

1

female

C

2

female

S

3

female

S

4

male

S

5

male

Q

6

male

S

7

male

S

8

female

S

9

female

C

from sklearn.preprocessing import OneHotEncoder

X = data.iloc[:,1:-1]

#可以直接一步到位

result = OneHotEncoder(categories='auto').fit_transform(X).toarray()

# # 也可以分开成两步计算

# enc = OneHotEncoder(categories='auto').fit(X)

# result = enc.transform(X).toarray()

# 把独热编码拼接到原数据上

newdata = pd.concat([data,pd.DataFrame(result)],axis=1)

newdata.drop(["Sex","Embarked"],axis=1,inplace=True)

newdata.columns = ["Age","Survived","Female","Male","Embarked_C","Embarked_Q","Embarked_S"]

newdata.head()

Age

Survived

Female

Male

Embarked_C

Embarked_Q

Embarked_S

0

22.0

0

0.0

1.0

0.0

0.0

1.0

1

38.0

2

1.0

0.0

1.0

0.0

0.0

2

26.0

2

1.0

0.0

0.0

0.0

1.0

3

35.0

2

1.0

0.0

0.0

0.0

1.0

4

35.0

0

0.0

1.0

0.0

0.0

1.0

(4) 使用pandas的.get_dummies函数 实现独热编码

dummies_Sex = pd.get_dummies(data.Sex,prefix='Sex') #ptefix 是前缀,因子化之后的字段名为 前缀_类名

dummies_Embarked = pd.get_dummies(data.Embarked,prefix='Embarked')

newdata = pd.concat([data, dummies_Sex, dummies_Embarked], axis=1) #将哑编码的内容拼接到data后

newdata.drop([ 'Sex', 'Embarked'], axis=1, inplace=True) # 把编码前的字段删除

newdata.head()

Age

Survived

Sex_female

Sex_male

Embarked_C

Embarked_Q

Embarked_S

0

22.0

0

0

1

0

0

1

1

38.0

2

1

0

1

0

0

2

26.0

2

1

0

0

0

1

3

35.0

2

1

0

0

0

1

4

35.0

0

0

1

0

0

1

4.处理连续特征:二值化和分段

(1) sklearn.preprocessing.Binarize 用于处理连续变量的二值化

根据阈值将数据二值化(将特征值设置为0或1),用于处理连续型变量。大于阈值的值映射为1,而小于或等于阈值的值映射为0。默认阈值为0。

# 将年龄二值化

data_2 = data.copy()

from sklearn.preprocessing import Binarizer

X = data_2.iloc[:,0].values.reshape(-1,1) #类为特征专用,所以不能使用一维数组

Age = Binarizer(threshold=30).fit_transform(X) # 以30为阈值,>30为1,<30为0

Age[:10]

array([[0.],

[1.],

[0.],

[1.],

[1.],

[0.],

[1.],

[0.],

[0.],

[0.]])

(2) sklearn.preprocessing.KBinsDiscretizer 用于给连续变量分箱

这是将连续型变量划分为分类变量的类,能够将连续型变量排序后按顺序分箱后编码。总共包含三个重要参数:

73d4fc632908ee91d7bce2d59986fdbe.png

from sklearn.preprocessing import KBinsDiscretizer

X = data.iloc[:,0].values.reshape(-1,1)

est = KBinsDiscretizer(n_bins=3, encode='ordinal', strategy='uniform') # 分箱后编码成分类数值

est.fit_transform(X)[:5]

array([[0.],

[1.],

[0.],

[1.],

[1.]])

est = KBinsDiscretizer(n_bins=3, encode='onehot', strategy='uniform') #查看转换后分的箱:变成了哑变量

est.fit_transform(X).toarray()

array([[1., 0., 0.],

[0., 1., 0.],

[1., 0., 0.],

...,

[0., 1., 0.],

[1., 0., 0.],

[0., 1., 0.]])

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值