pandas+sklearn数据预处理

1.未经与处理的数据可能存在的问题

  • 不属于同一量纲:即特征的规格不一样,不能够放在一起比较。无量纲化可以解决这一问题。
  • 信息冗余:对于某些定量特征,其包含的有效信息为区间划分,例如学习成绩,假若只关心“及格”或不“及格”,那么需要将定量的考分,转换成“1”和“0”表示及格和未及格。
  • 定性特征不能直接使用:某些机器学习算法和模型只能接受定量特征的输入,那么需要将定性特征转换为定量特征。最简单的方式是为每一种定性值指定一个定量值,但是这种方式过于灵活,增加了调参的工作。通常使用独热编码的方式将定性特征转换为定量特征:假设有N种定性值,则将这一个特征扩展为N种特征,当原始特征值为第i种定性值时,第i个扩展特征赋值为1,其他扩展特征赋值为0。独热编码的方式相比直接指定的方式,不用增加调参的工作,对于线性模型来说,使用独热编码后的特征可达到非线性的效果。
  • 存在缺失值:缺失值需要补充。
  • 信息利用率低:不同的机器学习算法和模型对数据中信息的利用是不同的,之前提到在线性模型中,使用对定性特征独热编码可以达到非线性的效果。类似地,对定量变量多项式化,或者进行其他的转换,都能达到非线性的效果。
  • 特征缺失:某些因素在原始数据中并不存在。

2.无量纲化
无量纲化使不同规格的数据转换到同一规格。常见的无量纲化方法有标准化、归一法和区间缩放法。
(1)标准化
标准化的前提是特征值服从正态分布,标准化后,其转换成标准正态分布。在已有样本足够多的情况下比较稳定,适合现代嘈杂大数据场景。
(2)区间放缩法
常用的方法是通过对原始数据进行线性变换把数据映射到[0,1]之间。在数据流场景下最大值与最小值是变化的。另外,最大值与最小值非常容易受异常点影响,所以这种方法鲁棒性较差,只适合传统精确小数据场景
(3)归一化
归一化是依照特征矩阵的行处理数据,其目的在于样本向量在点乘运算或其他核函数计算相似性时,拥有统一的标准,也就是说都转化为“单位向量”。此方法主要用于:(1)需要使用二次方程,比如点积或者其他核方法计算样本对之间的相似性(2)常用于文本分类和内容聚类的向量空间模型的基础。

3.pandas数据预处理
(1)缺失值的定义:
数据原本存在但是没被收集/数据根本不存在。
默认缺失值用NaN来表示,也可以通过设置用inf/-inf来表示:

pandas.options.mode.use_inf_as_na = True

时间序列中的缺失值用NaT来表示,pandas中NaN和NaT是兼容的。
(2)判断缺失值

df=pd.DataFrame(np.random.randn(5,3),index=['a','c','d','e','f'],columns=['one', 'two', 'three'])
df2 = df.reindex(['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'])
print(df2)
print(df2.isna())#输出的是布尔型变量
print(df2.notna())
print(df.isnull().sum())#输出每一列缺失值的个数
print(df.isnull().count())#输出每一列值的个数

(3)缺失值赋值
给缺失值赋值可以通过np.nan或None进行。当被赋值的是数值型的容器,缺失值的形式为nan,当被赋值的是对象型的容器,缺失值的形式保留为原始输入的形式(None or nan)
(4)缺失值计算
下面是含有缺失值数据的一些计算规则。
求和时缺失数据会被默认是0;
求累加或累乘时被自动忽略,也可以通过设置skipna=False让它不被忽略,从而整个结果都成为nan;
完全为空的dataframe求和为0,乘积为1;
dataframe分组中缺失数据会被自动忽略。
(5)过滤缺失值

df=pd.DataFrame([[1,6.5,3],[1,np.nan,np.nan],[np.nan,np.nan,np.nan],[np.nan,6.5,3]])
print(df)
print(df.dropna())#默认只要包含nan就把那一行删去
print(df.dropna(how='all'))#整行都是nan才删去
print(df.dropna(axis=1))#把包含nan的列删去(所以最后输出了一个空的dataframe,全部被删掉了)
>>>
      0    1    2
0  1.0  6.5  3.0
1  1.0  NaN  NaN
2  NaN  NaN  NaN
3  NaN  6.5  3.0
     0    1    2
0  1.0  6.5  3.0
     0    1    2
0  1.0  6.5  3.0
1  1.0  NaN  NaN
3  NaN  6.5  3.0
Empty DataFrame
Columns: []
Index: [0, 1, 2, 3]

(6)填充缺失数据(重要)
fillna()用于填充缺失数据

print(df.fillna('not exist'))#用于填充的值可以是各种形式
print(df.fillna(0))
print(df.fillna({1:0,2:1}))#不同的列可以按不同值填充
print(df.fillna(df.mean()))#列均值填充
print(df.fillna(method='ffill',limit=2))#用前项填充,最多填充二项
print(df.fillna(method='backfill'))#用后一项填充

插值法填充数据
interpolate()可用插值法填充数据,默认使用方式如下。

interpolate(method='linear', axis=0, limit=None, inplace=False, limit_direction='forward', limit_area=None, downcast=None, **kwargs)
#默认按照线性的方式填充,axis=0默认按列填充,limit_direction默认按前向填充

插值填充方法还有很多种:‘linear’, ‘time’, ‘index’, ‘values’, ‘nearest’, ‘zero’,‘slinear’, ‘quadratic’, ‘cubic’, ‘barycentric’, ‘krogh’, ‘polynomial’, ‘spline’, ‘piecewise_polynomial’,
‘from_derivatives’, ‘pchip’, ‘akima’
具体可见文档:https://docs.scipy.org/doc/scipy/reference/tutorial/interpolate.html
以增加的增速增长的时间序列数据:method=‘quadratic’
估计累计概率密度函数:method=‘pchip’
为了画图:method=‘akima’
(7)删除重复值

data=pd.DataFrame({'k1':['one','two']*3+['two'],'k2':[1,1,2,3,3,4,4]})
print(data)
print(data.duplicated())#显示重复的行
print(data.drop_duplicates())#删除重复的行
data['k3']=np.arange(7)
print(data.drop_duplicates(['k1','k2']))#按k1k2删除重复的行
>>>
    k1  k2
0  one   1
1  two   1
2  one   2
3  two   3
4  one   3
5  two   4
6  two   4
0    False
1    False
2    False
3    False
4    False
5    False
6     True
dtype: bool
    k1  k2
0  one   1
1  two   1
2  one   2
3  two   3
4  one   3
5  two   4
    k1  k2  k3
0  one   1   0
1  two   1   1
2  one   2   2
3  two   3   3
4  one   3   4
5  two   4   5

(8)替代值
fillna其实是replace的特殊用法,一般的替代用法如下。

data=pd.Series([1,-999,2,-999,-1000,3])
print(data.replace(-999,np.nan))
print(data.replace([-999,-1000],[np.nan,0]))
print(data.replace({-999:np.nan,-1000:0}))
>>>
0       1.0
1       NaN
2       2.0
3       NaN
4   -1000.0
5       3.0
dtype: float64
0    1.0
1    NaN
2    2.0
3    NaN
4    0.0
5    3.0
dtype: float64
0    1.0
1    NaN
2    2.0
3    NaN
4    0.0
5    3.0
dtype: float64

4.sklearn数据预处理
4.1 标准化
(1)标准化
Standardization标准化:将特征数据的分布调整成标准正态分布,也叫高斯分布,也就是使得数据的均值维0,方差为1.标准化的原因在于如果有些特征的方差过大,则会主导目标函数从而使参数估计器无法正确地去学习其他特征。

# 创建一组特征数据,每一行表示一个样本,每一列表示一个特征
X_train = np.array([[ 1., -1.,  2.],[ 2.,  0.,  0.],[ 0.,  1., -1.]])
X_scale=preprocessing.scale(X_train)
print(X_scale)
print(X_scale.mean(axis=0))#按列求均值
print(X_scale.std(axis=0))
>>>
[[ 0.         -1.22474487  1.33630621]
 [ 1.22474487  0.         -0.26726124]
 [-1.22474487  1.22474487 -1.06904497]]
[0. 0. 0.]
[1. 1. 1.]

preprocessing这个模块还提供了一个实用类StandarScaler,它可以在训练数据集上做了标准转换操作之后,把相同的转换应用到测试训练集中。这个功能可以对训练数据,测试数据应用相同的转换,以后有新的数据进来也可以直接调用,不用再重新把数据放在一起再计算一次了。
StandardScaler()中可以传入两个参数:with_mean,with_std.这两个都是布尔型的参数,默认情况下都是true,但也可以自定义成false.即不要均值中心化或者不要方差规模化为1.

# 调用fit方法,根据已有的训练数据创建一个标准化的转换器
scaler = preprocessing.StandardScaler().fit(X_train)
print(scaler.transform(X_train))#把转换器用在训练数据上
X_new=[[1,2,3]]
print(scaler.transform(X_new))#把转换器用在新数据上

(2)将特征缩放至特定范围内
一种标准化是将特征缩放到给定的最小值和最大值之间,通常在0和1之间,或者也可以将每个特征的最大绝对值转换至单位大小。可以分别使用 MinMaxScaler 和 MaxAbsScaler 实现。
MinMaxScaler
在MinMaxScaler中是给定了一个明确的最大值与最小值

#调用方法和上面类似,现根据训练数据创建一个放缩转换器
minmax_scaler=preprocessing.MinMaxScaler().fit(X_train)
#把转换器用在训练数据
X_minmax=minmax_scaler.transform(X_train)
print(X_minmax)
#把转换器用在新数据
X_new_minmax=minmax_scaler.transform(X_new)
print(X_new_minmax)

MaxAbsScaler
**原理与上面的很像,只是数据会被规模化到[-1,1]之间。**也就是特征中,所有数据都会除以最大值。这个方法对那些已经中心化均值维0或者稀疏的数据有意义。

maxabs_scaler=preprocessing.MaxAbsScaler().fit(X_train)
X_maxabs=maxabs_scaler.transform(X_train)
print(X_maxabs)
X_new_maxabs=maxabs_scaler.transform(X_new)
print(X_new_maxabs)
>>>
[[ 0.5 -1.   1. ]
 [ 1.   0.   0. ]
 [ 0.   1.  -0.5]]
[[0.5 2.  1.5]]

(3)特殊数据
规模化稀疏数据:MaxAbsScaler
规模化异常值数据:RobustScaler,它会根据中位数或者四分位数去中心化数据。
(4)非线性转换
非线性转换主要有两种:分位数转换和幂函数转换。分位数和幂变换都基于特征的单调变换,从而保持了每个特征值的秩。

4.2 正则化/归一化
归一化是缩放单个样本以具有单位范数的过程。如果你计划使用二次形式(如点积或任何其他核函数)来量化任何样本间的相似度,则此过程将非常有用。这个观点基于 向量空间模型(Vector Space Model) ,经常在文本分类和内容聚类中使用.
函数 normalize 提供了一个快速简单的方法在类似数组的数据集上执行操作,使用 l1 或 l2 范式。

normalizer = preprocessing.Normalizer(norm='l2').fit(X_train)
X_normalized=normalizer.transform(X_train)
print(X_normalized)
X_new_normalized=normalizer.transform(X_new)
print(X_new_normalized)

4.3特征的二值化
将数值型的特征数据转换成布尔类型的值,默认以0为阈值。可以使用实用类Binarizer。

binarized=preprocessing.Binarizer(threshold=1).fit(X_train)#把1设置为阈值
X_binarized=binarized.transform(X_train)
print(X_binarized)

4.4类别特征编码
在机器学习中,特征经常不是连续的数值型的而是标称型的(categorical)。举个例子,一个人的样本具有特征[“male”, “female”], [“from Europe”, “from US”, “from Asia”], [“uses Firefox”, “uses Chrome”, “uses Safari”, “uses Internet Explorer”] 等。 这些特征能够被有效地编码成整数,比如 [“male”, “from US”, “uses Internet Explorer”] 可以被表示为 [0, 1, 3],[“female”, “from Asia”, “uses Chrome”] 表示为 [1, 2, 1]。
OrdinalEncoder
要把标称型特征(categorical features) 转换为这样的整数编码(integer codes), 我们可以使用 OrdinalEncoder。

X = [['male', 'from US', 'uses Safari'], ['female', 'from Europe', 'uses Firefox']]
enc=preprocessing.OrdinalEncoder().fit(X)
X_train=[['female', 'from US', 'uses Safari']]
X_encoded=enc.transform(X_train)
print(X_encoded)
print(enc)
>>>
[[0. 1. 1.]]
OrdinalEncoder(categories='auto', dtype=)

独热码
另外一种将标称型特征转换为能够被scikit-learn中模型使用的编码是one-of-K, 又称为 独热码或dummy encoding。 这种编码类型已经在类OneHotEncoder中实现。该类把每一个具有n_categories个可能取值的categorical特征变换为长度为n_categories的二进制特征向量,里面只有一个地方是1,其余位置都是0

X = [['male', 'from US', 'uses Safari'], ['female', 'from Europe', 'uses Firefox']]
enc=preprocessing.OneHotEncoder().fit(X)#用x训练出一个编码模型
X_encoded=enc.transform(X).toarray()
print(X_encoded)
>>>
[[0. 1. 0. 1. 0. 1.]
 [1. 0. 1. 0. 1. 0.]]

更加清晰的表示方法

genders = ['female', 'male']##一开始就把类别指定清楚
locations = ['from Africa', 'from Asia', 'from Europe', 'from US']
browsers = ['uses Chrome', 'uses Firefox', 'uses IE', 'uses Safari']
enc = preprocessing.OneHotEncoder(categories=[genders, locations, browsers])
X = [['male', 'from US', 'uses Safari'], ['female', 'from Europe', 'uses Firefox']]
enc=preprocessing.OneHotEncoder().fit(X)
X_encoded=enc.transform(X).toarray()
print(X_encoded)

由于训练数据可能缺少分类特性,通常最好指定handle_unknown=‘ignore’,而不是像上面那样手动设置类别。当指定handle_unknown=‘ignore’,并且在转换过程中遇到未知类别时,不会产生错误,但是为该特性生成的一热编码列将全部为零。

enc = preprocessing.OneHotEncoder(handle_unknown='ignore')

4.5离散化
离散化 (Discretization) 或 装箱(binning))提供了将连续特征划分为离散特征值的方法。 某些具有连续特征的数据集会受益于离散化,因为 离散化可以把具有连续属性的数据集变换成只有名义属性(nominal attributes)的数据集。One-hot 编码的离散化特征 可以使得一个模型更加的有表现力,同时还能保留其可解释性。 比如,用离散化器进行预处理可以给线性模型引入非线性。
KBinsDiscretizer 类使用k个等宽的bins把特征离散化。
KBinsDiscretizer类实现了不同的 binning策略,可以通过参数strategy进行选择。 ‘uniform’ 策略使用固定宽度的bins。 ‘quantile’ 策略在每个特征上使用分位数(quantiles)值以便具有相同填充的bins。 ‘kmeans’ 策略基于在每个特征上独立执行的k-means聚类过程定义bins。
pandas+sklearn数据预处理_第1张图片encode表示分享结果的表示方式。包括’onehot’(默认), ‘onehot-dense’, ‘ordinal’。
onehot是将结果用稀疏独热矩阵表示,onehot-dense将结果用密集独热矩阵表示,ordinal将结果用普通整数表示(生活中最常用的那种)

X = [[-2, 1, -4, -1],[1, 2, -3, -0.5],[ 0, 3, -2,0.5],[ 1, 4, -1,2]]
est =preprocessing.KBinsDiscretizer(n_bins=3, encode='ordinal', strategy='uniform').fit(X)#nbins指的是有界边界的个数,实际上还包含两侧的半开区间
Xt=est.transform(X)
print(X)
print(Xt)
#print(est)
print(est.bin_edges_)#输出每一个特征的划分边界
>>>>
[[-2, 1, -4, -1], [1, 2, -3, -0.5], [0, 3, -2, 0.5], [1, 4, -1, 2]]#原始数据,每列为一个特征
[[0. 0. 0. 0.]
 [2. 1. 1. 0.]
 [2. 2. 2. 1.]
 [2. 2. 2. 2.]]
[array([-2., -1.,  0.,  1.]) array([1., 2., 3., 4.])
 array([-4., -3., -2., -1.]) array([-1.,  0.,  1.,  2.])]#第一个array意思是把第一个特征按照(-∞,-2],[-2,-1],[-1,0],[0,1],[1,+∞)

4.6缺失值处理
因为各种各样的原因,真实世界中的许多数据集都包含缺失数据,这类数据经常被编码成空格、NaNs,或者是其他的占位符。但是这样的数据集并不能scikit-learn学习算法兼容, **使用不完整的数据集的一个基本策略是舍弃掉整行或整列包含缺失值的数据,**但这样就付出了舍弃可能有价值数据(即使是不完整的 )的代价。 处理缺失数值的一个更好的策略就是从已有的数据推断出缺失的数值
(1)单变量插补
SimpleImputer类提供了计算缺失值的基本策略。缺失值可以用提供的常数值计算,也可以使用缺失值所在的行/列中的统计数据(平均值、中位数或者众数)来计算。这个类也支持不同的缺失值编码。

#对普通矩阵的缺失值用每一列的均值填补
X=[[1, 2], [np.nan, 3], [7, 6]]
imp=Imputer(missing_values="NaN",strategy="mean",).fit(X)
X_train=[[np.nan, 2], [6, np.nan], [7, 6]]
X_transformed=imp.transform(X_train)
print(X_transformed)
#对稀疏矩阵的操作,把0作为缺失值
Y = sp.csc_matrix([[1, 2], [0, 3], [7, 6]])
imp=Imputer(missing_values="NaN",strategy="mean",).fit(Y)
Y_train=[[0, 2], [6, 0], [7, 6]]
Y_transformed=imp.transform(Y_train)
print(Y_transformed)
#对分类变量也可以操作,用出现频率最高的数据进行填补
df = pd.DataFrame([["a", "x"],[np.nan, "y"],["a", np.nan],["b", "y"]], dtype="category")
imp = Imputer(strategy="most_frequent").fit(df)
z_train=pd.DataFrame([["a", "x"],[np.nan, "y"],["a", np.nan],["b", "y"],["c","z"]], dtype="category")
z_transformed=imp.transform(z_train)
print(z_transformed)
##最后一个不知道为什么输出结果报错
>>>
[[4.         2.        ]
 [6.         3.66666667]
 [7.         6.        ]]
[[0. 2.]
 [6. 0.]
 [7. 6.]]

(2)多变量插补
一种更复杂的方法是使用IterativeImputer类,它将每个缺失值的特征建模为其他特征的函数,并使用该估计值进行估算。它以迭代循环方式执行:在每个步骤中,将要素目标列指定为输出y,将其他列视为输入X。使用一个回归器来在已知(未缺失)y的样本上,对(X,y)进行拟合。然后使用这个回归器来预测缺失的y值。这是以迭代的方式对每个特征进行的,然后重复max_iter轮。最后一轮的计算结果被返回。
***填补工具还在测试阶段,以后再补。

你可能感兴趣的:(python)