用Python进行数据挖掘(数据预处理)2018-04-22

转自:https://blog.csdn.net/u011094454/article/details/77618604
本博客进行数据预处理的方法总结自kaggle的几道题目:
1.HousePrices
2.Titanic
以及比较不错的几个kernels:
1.https://www.kaggle.com/pmarcelino/house-prices-advanced-regression-techniques/comprehensive-data-exploration-with-python/run/1432348
2.https://www.kaggle.com/sinakhorami/titanic-best-working-classifier
3.https://www.kaggle.com/apapiu/regularized-linear-models
4.https://www.kaggle.com/serigne/stacked-regressions-top-4-on-leaderboard
本博客只能稍微了解下数据预处理,入门都算不上,真正想要深入学习特征工程建议应该先刷完sklearn的数据预处理API文档:
http://scikit-learn.org/stable/modules/preprocessing.html#preprocessing

  • 数据加载与粗略查看
  • 处理丢失的数据
  • 处理偏离值
  • 数据统计
  • 特征值的合并、连接
  • 数据转换、标准化、归一化

数据加载与粗略查看

数据加载

一般训练与测试的数据都提供csv格式,使用pandas库读取:

df_train = pd.read_csv('../train.csv')

此时读取的df_train为DataFrame格式。
同时pandas还可以读取各种不同格式的数据,如存储比较快的hdf格式、excel等

但有时数据不是简单的csv,它按照文本保存,如“ID||texttexttexttext”这样的一条数据需要将中间的“||”当作分隔符,读取方式如下:

train = pd.read_csv('../input/training_text', sep="\|\|", engine='python', header=None, skiprows=1, names=["ID","Text"])

更多参数应该查阅pandas文档。

数据粗略查看

在pandas读进来数据一个train后,train的格式为DataFrame,调用下面的几个方法就可以大致了解我们得到的数据是什么,有什么特征值,特征值的数据类型是什么,如果是数值那么最大最小值是什么等:

train.head(5)     #显示前5行数据
train.tail(5)     #显示后5行
train.columns    #查看列名
train.info()     #查看各字段的信息
train.shape      #查看数据集行列分布,几行几列
train.describe() #查看数据的大体情况

如train.describe():


train.describe()

处理丢失的数据

处理这些数据以前不建议把train与test 连接起来,因为这样容易造成test里数据的丢失,个人认为较好的方式为:

full_data = [train, test]

将两个数据集合成为list,然后清洗时对其for循环即可,如:

for dataset in full_data:
    dataset['FamilySize'] = dataset['SibSp'] + dataset['Parch'] + 1

下面只介绍对测试集train 的操作。

找到丢失的位置

输出每个列丢失值也即值为NaN的数据和,并从多到少排序:

total = train.isnull().sum().sort_values(ascending=False)
print(total)
Cabin          687
Age            177
Embarked         2
Fare             0
Ticket           0
Parch            0
SibSp            0
Sex              0
Name             0
Pclass           0
Survived         0
PassengerId      0

也可以输出百分比:

percent =(train.isnull().sum()/train.isnull().count()).sort_values(ascending=False)
missing_data = pd.concat([total, percent], axis=1, keys=['Total', 'Percent'])
missing_data.head(20)
这里写图片描述

由此可以看到‘Cabin’的缺失数量最多,‘Embarked’最少。

缺失值得处理

对缺失数据的处理我们有很多方法,如《机器学习实战》里提到:

  1. 使用可用特征的均值来填补缺失值;
  2. 使用特殊值来填补缺失值,如-1;
  3. 忽略有缺失值的样本;
  4. 使用相似样本的均值添补缺失值;
  5. 使用另外的机器学习算法预测缺失值。

填补

#使用出现次数最多的值填补
train['Embarked'] = train['Embarked'].fillna('S')
train.product_type[train.product_type.isnull()]=train.product_type.dropna().mode().values

这里的特殊值是在这个特征下出现最多的一个值,特殊值的选取需要根据情况来判断,中位数也是特殊值:

#使用中位数填补
train['Fare'] = train['Fare'].fillna(train['Fare'].median())
使用平均数填补
train['Age'] = train['Age'].fillna(train['Age'].mean())
train['LotFrontage'].fillna(train['LotFrontage'].mean())

忽略

根据情况可以选择忽略这一特征的列和忽略出现缺失的那几行。
通常后者出现在缺失的行数比较少的情况下。

#去掉一列
train = train.drop(['Cabin'], axis = 1)
#去掉这个特征为空的行
#当然后面可以加上inplace=True表示直接就在内存中替换了不用再赋值个train_new,但是本人多次删除掉几个行,发现有问题时又需要重新建立已经分析好的train,很浪费时间,个人认为还是重新开辟一个比较好
train_new = train.drop(train[train['Embarked'].isnull()].index)
#返回已经去掉重复行的数据集
train.drop_duplicates()

处理偏离值

查找偏离值

将数据可视化(python中的pyplot),观察异常值,引用HousePrice中的一个例子:

#bivariate analysis saleprice/grlivarea
var = 'GrLivArea'
data = pd.concat([df_train['SalePrice'], df_train[var]], axis=1)
data.plot.scatter(x=var, y='SalePrice', ylim=(0,800000));
这里写图片描述

可以发现,有四个点在非常偏离的位置,先讨论上面两个偏移位。
在下方无数点形成非常好的线性关系,那这偏移很大的两点是异常值吗?不是,虽然偏离位置很远,但是与下面无数点形成的线性关系还是拟合的。
再看看右下两个值,显然它们偏离得没有道理,删!

删除偏离值

train.sort_values(by = 'GrLivArea', ascending = False)[:2]
train= train.drop(train[train['Id'] == 1299].index)
train= train.drop(train[train['Id'] == 524].index)

保留偏离值

当然并不是所有的偏离值都需要删除,具体需要在分析之后选择处理方式。这里将偏离值保留下来并不是原封不动保留,而需要做标准化或归一化处理,具体的处理方式可查看最后一节数据转换、标准化、归一化。

数据统计

现在我们已经拿到了一份比较完整的数据,让我们开始对它做一个简单的统计。
统计包括数据的偏斜度、峰度、不同特征值的相关系数、协方差、均值等。

#统计某一列中各个元素值出现的次数
train['MSSubClass'].value_counts()   
 #     
#列出数据的偏斜度
train['MSSubClass'].skew()    

#列出数据的峰度
train['MSSubClass'].kurt()   

#计算两个列的相关度
train['LotFrontage'].corr(train['LotArea'])   

#观察两个列的值的二维图
x = 'GrLivArea';y = 'SalePrice'
data = pd.concat([train[y], train[x]], axis=1)
data.plot.scatter(x=x, y=y, ylim=(0,800000));#这里800000为y的最大值

#计算所有特征值每两个之间的相关系数,并作图表示。
corrmat = train.corr()#得到相关系数
f,ax = plt.subplots(figsize = (12,9))
sns.heatmap(corrmat, vmax = .8, square = True)#热点图

#取出相关性最大的前十个,做出热点图表示
k = 10 #number of variables for heatmap
cols = corrmat.nlargest(k, 'SalePrice')['SalePrice'].index
cm = np.corrcoef(train[cols].values.T)
sns.set(font_scale=1.25)
hm = sns.heatmap(cm, cbar=True, annot=True, square=True, fmt='.2f',     annot_kws={'size': 10}, yticklabels=cols.values,    xticklabels=cols.values)
plt.show()

热点图展示:


这里写图片描述

特征值的合并、连接

在合并连接之前,我们需要了解pandas.groupby这个分组方法,因为很多时候我们是在从几个特征值里挖掘一些值来当作新的特征值,这样子我们这个分组的方法就显得尤为重要了,如按照同一个用户进行分组来计算这个用户的行为次数当作新的特征值等等

分组的常用代码块

#按照用户分组---------------------一个特征值
train.groupby('userid',as_index=False)
#按照用户与目的地分组---------------两个特征值
train.groupby(['userid','end_loc'],as_index=False)
#用户、起点、目的地-----------------三个特征值
train.groupby(['userid','start_loc','end_loc'],as_index=False)
#跟MSSubClass进行分组,并求分组后的平均值
train[['MSSubClass', 'LotFrontage']].groupby(['MSSubClass'], as_index=False).mean()
#选取特定的属性的某个值然后进行分类
train[train['date']=='2017-1-2'].groupby(['userid'],as_index=False)  

按照分组的结果,得到需要的信息然后合并

#获得分组后,统计分组中'end_loc'的数量返回为一列由‘userid’和‘user_count’组成的新的DataFrame
user_count = train.groupby('userid',as_index=False)['end_loc'].agg({'user_count':'count'})
#将获得的新的DataFrame合并到train,更多的merge参数请查阅文档
train= pd.merge(train,user_count,on=['userid'],how='left')

user_eloc_count = train.groupby(['userid','end_loc'],as_index=False)['userid'].agg({'user_eloc_count':'count'})
train= pd.merge(train,user_eloc_count,on=['userid','end_loc'],how='left')

数据的连接

#讲训练数据与测试数据连接起来,以便一起进行数据清洗。
#这里需要注意的是,如果没有后面的ignore_index=True,那么index的值在连接后的这个新数据中是不连续的,如果要按照index删除一行数据,可能会发现多删一条。
merge_data=pd.concat([train,test],ignore_index=True)  

#另一种合并方式,按列名字进行合并。
all_data = pd.concat((train.loc[:,'MSSubClass':'SaleCondition'], test.loc[:,'MSSubClass':'SaleCondition']))  

数据转换、标准化、归一化

数值转换

#浮点型数值转换为整型
train['Age']=train['Age'].astype(int)

#字符串的替换--映射
train['MSZoning']=train['MSZoning'].map({'RL':1,'RM':2,'RR':3,}).astype(int)
train['Embarked'] = train['Embarked'].map( {'S': 0, 'C': 1, 'Q': 2} ).astype(int)
#一般建议将map拿出来
title_mapping = {"Mr": 1, "Miss": 2, "Mrs": 3, "Master": 4, "Rare": 5}
train['Title'] = train['Title'].map(title_mapping)
train['Title'] = train['Title'].fillna(0)

#将字符串特征列中的内容分别提出来作为新的特征出现,表现为0、1。
train= pd.get_dummies(houseprice)   

#将连续型特征值分块,每一块用数字标识
train.loc[ train['Fare'] <= 7.91, 'Fare'] = 0
train.loc[(train['Fare'] > 7.91) & (train['Fare'] <= 14.454), 'Fare'] = 1
train.loc[(train['Fare'] > 14.454) & (train['Fare'] <= 31), 'Fare']   = 2
train.loc[ train['Fare'] > 31, 'Fare'] = 3
train['Fare'] = train['Fare'].astype(int)

下面这个数值转换是将数值进行log计算,使分布的数值显常态

train['SalePrice'] = np.log(train['SalePrice'])

而有时这样的log不可行,就需要使用log(x+1)来 处理,至于原因请点击链接

train["SalePrice"] = np.log1p(train["SalePrice"])
#将偏斜度大于0.75的数值列log转换,使之尽量符合正态分布。
skewed_feats = train[numeric_feats].apply(lambda x: skew(x.dropna())) #compute skewness
skewed_feats = skewed_feats[skewed_feats > 0.75]
skewed_feats = skewed_feats.index
all_data[skewed_feats] = np.log1p(all_data[skewed_feats])
这里写图片描述

数据标准化和归一化(Standardization、Normalization)

标准化归一化概念不再赘述,实际使用时最主要的还是要了解什么时候需要标准化,什么时候用归一化,还需要清楚当前数据适合什么标准化方式等等。
sklearn.preprocessing 介绍的标准化方式有:
1. preprocessing.scale()、preprocessing.StandardScaler(),使数据集呈现标准正态分布,即mean = 0,且标准差std = 1。
2. MinMaxScaler 、MaxAbsScaler,前者使数据集分布在[0,1],后者分布在[-1,1]。这种方式通常在(1) 特征的标准差较小 (2) 可以使稀疏数据集中的0值继续为0,这两种情况下使用。
3. preprocessing.QuantileTransformer(),将数据映射到[0,1]之间均匀分布,会破坏原数据之间的相关特性。
4. 归一化方式:preprocessing.normalize(),将样本缩放成单位向量,(1)需要使用二次方程,比如点积或者其他核方法计算样本对之间的相似性(2)常用于文本分类和内容聚类的向量空间模型的基础。

</article>

版权声明:随意转载,不用告诉我,但链接到就行。 https://blog.csdn.net/u011094454/article/details/77618604

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,440评论 5 467
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,814评论 2 376
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,427评论 0 330
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,710评论 1 270
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,625评论 5 359
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,014评论 1 275
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,511评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,162评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,311评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,262评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,278评论 1 328
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,989评论 3 316
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,583评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,664评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,904评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,274评论 2 345
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,856评论 2 339

推荐阅读更多精彩内容