为数据挖掘与机器学习过程中提供干净、准确、简洁的数据,提高数据挖掘的准确性和效率,数据预处理是特别重要的一部分,它在数据挖掘整个流程中可以占到70%的处理时间。
数据标准化是为了消除不同指标量纲的影响,方便指标间的可比性,量纲差异会影响某些模型中距离计算的结果。
有些数据挖掘算法,特别是分类算法,要求数据是分类属性形式,发现关联模式的苏纳法要求是二值属性格式。这样,常常要将连续属性变换成分类属性(离散化)并且连续和离散属性可能都需要变换成一个或多个二元属性(二值化)。
分类值 | 整数值 | x1 | x2 | x3 | x4 | x5 |
---|---|---|---|---|---|---|
awful | 0 | 1 | 0 | 0 | 0 | 0 |
poor | 1 | 0 | 1 | 0 | 0 | 0 |
ok | 2 | 0 | 0 | 1 | 0 | 0 |
good | 3 | 0 | 0 | 0 | 1 | 0 |
great | 4 | 0 | 0 | 0 | 0 | 1 |
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif'] =['Microsoft YaHei']
plt.rcParams['axes.unicode_minus'] = False
data=pd.read_csv('qunar_freetrip.csv',index_col=0)
data.info()
<class 'pandas.core.frame.DataFrame'>
Int64Index: 5100 entries, 0 to 5099
Data columns (total 13 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 出发地 5098 non-null object
1 目的地 5099 non-null object
2 价格 5072 non-null float64
3 节省 5083 non-null float64
4 路线名 5100 non-null object
5 酒店 5100 non-null object
6 房间 5100 non-null object
7 去程航司 5100 non-null object
8 去程方式 5100 non-null object
9 去程时间 5100 non-null object
10 回程航司 5100 non-null object
11 回程方式 5100 non-null object
12 回程时间 5100 non-null object
dtypes: float64(2), object(11)
memory usage: 557.8+ KB
# 存在缺失值:价格、节省、目的地、出发地
#去除空格
data.columns = [x.strip() for x in data.columns] # 列名可能存在空格 去除
#均值填补价格和节省缺失值
data['价格'].fillna(round(data['价格'].mean()), inplace=True)
data['节省'].fillna(round(data['节省'].mean()), inplace=True)
data[data['出发地'].isnull() | data['目的地'].isnull()] # 部分结果
出发地 目的地 价格 节省 路线名
NaN 烟台 647.0 348.0 大连-烟台3天2晚 | 入住烟台海阳黄金海岸
深圳 NaN 2149.0 494.0 深圳-大连3天2晚 | 入住大连黄金山大酒店
NaN 西安 1030.0 326.0 济南-西安3天2晚 | 入住西安丝路秦国际青年旅舍钟楼回民街店
# 知道路线名,所以我们可以从路线名中提取出发地和目的地
# 从路线名提取地点,填充缺失值
data.loc[data['出发地'].isnull(), '出发地'] = [str(x)[:2] for x in data.loc[data['出发地'].isnull(), '路线名']]
data.loc[data['目的地'].isnull(), '目的地'] = [str(x)[:2] for x in data.loc[data['目的地'].isnull(), '路线名']]
# 结果看没有缺失值了
<class 'pandas.core.frame.DataFrame'>
Int64Index: 5100 entries, 0 to 5099
Data columns (total 13 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 出发地 5100 non-null object
1 目的地 5100 non-null object
2 价格 5100 non-null float64
3 节省 5100 non-null float64
4 路线名 5100 non-null object
5 酒店 5100 non-null object
6 房间 5100 non-null object
7 去程航司 5100 non-null object
8 去程方式 5100 non-null object
9 去程时间 5100 non-null object
10 回程航司 5100 non-null object
11 回程方式 5100 non-null object
12 回程时间 5100 non-null object
dtypes: float64(2), object(11)
memory usage: 557.8+ KB
data.duplicated().sum() # 100 输出重复值数量
data=data.drop_duplicates() # 删除重复值
# 删除异常值(价格<节省)
data = data[data['节省'] <= data['价格']]
data.describe().T
count mean std min 25% 50% 75% max
价格 4997.0 1768.276566 2597.723990 578.0 1256.0 1637.0 2029.0 179500.0
节省 4997.0 472.796878 154.090652 306.0 358.0 436.0 530.0 1640.0
# 结果中 看出价格中最高179500元,属于异常值;节省中1640元也属于异常值,因为它们远远高于各自的3/4位数
# 处理异常值 截取 价格或节省的钱在 [3/4位数-1.5*(3/4位数-1/4位数,1/4位数+1.5*(3/4位数-1/4位数)]
price_h = data['价格'].quantile(q=0.75)
price_l = data['价格'].quantile(q=0.25)
sub_h = data['节省'].quantile(q=0.75)
sub_l = data['节省'].quantile(q=0.25)
data = data[(data['价格']< price_l+1.5*(price_h-price_l)) & (data['价格']>price_h-1.5*(price_h-price_l))]
data = data[(data['节省']< sub_l+1.5*(sub_h-sub_l)) & (data['节省']>sub_h-1.5*(sub_h-sub_l))]
# 查看两个特征的箱线图
fig= plt.figure(figsize=(10,3))
ax1 = fig.add_subplot(121)
plt.boxplot(data['价格'])
plt.title('价格')
ax2 = fig.add_subplot(122)
plt.boxplot(data['节省'])
plt.title('节省')
plt.show()
from sklearn.preprocessing import minmax_scale,StandardScaler # 最小最大标准化 、均值方差标准化
df = pd.DataFrame()
df['价格1'] = minmax_scale(data['价格'])
df['节省1'] = minmax_scale(data['节省'])
df['价格2'] = StandardScaler().fit_transform(np.array(data['价格']).reshape(-1,1))
df['节省2'] = StandardScaler().fit_transform(np.array(data['节省']).reshape(-1,1))
round(df['价格1'].min(),2),round(df['价格1'].max(),2) # (0.0, 1.0) 最小—最大值标准化 即最小值为0 最大值为1
round(df['价格2'].mean(),2),round(df['价格2'].std()**2,2) # (0.0, 1.0) 均值方差标准化服从标准正态分布 即 均值为0,方差为1
way_dummis=pd.get_dummies(data['去程方式'])
way_dummis
from sklearn.preprocessing import OneHotEncoder
a = np.array(data['去程方式']).reshape(-1,1) # 转成二维矩阵
b = OneHotEncoder(categories='auto').fit(a) # 拟合数据
way = b.transform(a).toarray() # #输出转化值
way
array([[1., 0.],
[1., 0.],
[1., 0.],
...,
[1., 0.],
[0., 1.],
[1., 0.]])
b.get_feature_names() #获取转换后数值的标签
array(['x0_直飞', 'x0_经停'], dtype=object)