大数据比赛第一步——数据分析
前言
大家好,我是机器学习领域的新手,最近新开了《从零开始的机器学习之旅》专栏,希望能与大家共同进步,如有错误和意见请不吝指出,谢谢。
最近看了一些比赛code,也自己试着提交了一下,真正体验到比赛的乐趣。但是,光看代码提高不了比赛能力,总结才是王道。所以我打算做一个系列,总结成模板,方便能有部分思路能够应用到以后的所有比赛中。
系列包括:
- 数据分析
- 特征工程
- 模型训练
- 模型融合
数据分析
对数据的分析,无疑是十分重要的。
毕竟数据里属性(特征)众多,我们对数据进行分析,可以找出哪些属性对标签的影响更为重要,哪些特征没有作用,甚至对结果(标签)产生负影响等等。
还可以找出哪些属性有缺失值,哪些属性可以合并生成新属性等等,当然我们在后续【特征工程】部分会进行处理。
一、加载数据
1.1 准备工作
首先,无脑导入numpy和pandas准没错。而为了做数据分析画图是必须的,因此导入seaborn和matplotlib
import pandas as pd #数据分析 import numpy as np #科学计算 from pandas import Series,DataFrame import seaborn as sns import matplotlib.pyplot as plt %matplotlib inline
1.2 数据导入
这是不管做什么项目、比赛的第一步,巧妇难为无米之炊,有了数据才能开始干活。我没有设置工作路径,数据和程序放在同一个文件夹。
train = pd.read_csv("train.csv")
test = pd.read_csv("test.csv")
一般的小比赛,只有训练集和测试集,直接导入即可。
1.3 数据合并
1.3.1 merge
有的大比赛,会有好几个csv文件,我们导入后,在对数据进行一定了解后,可以进行merge合并。
train=train1.merge(train2,how='left',on='userID')
这里用到了merge函数。把训练集1和训练集2按照userID合并。
DataFrame.merge(*right*, *how='inner'*, *on=None*, *left_on=None*, *right_on=None*, *left_index=False*, *right_index=False*, *sort=False*, *suffixes=('_x'*, *'_y')*, *copy=True*, *indicator=False*, *validate=None*)
我主要用到how
和on
两个参数。on
用来指明要加入的列 (名称)。必须在左、 右综合对象中找到。how
指明merge的方式,一共有四种。
- left:只使用左边框的键,类似于SQL左外部连接; 保持按键顺序
- right:仅使用右框架中的键,类似于SQL右外连接; 保持按键顺序
- outer:使用两个框架中的键的联合,类似于SQL全外连接; 按字典顺序排序键
- inner:使用来自两个框架的键的交集,类似于SQL内部联接; 保留左键的顺序
看到有人说的不错,引用下:
df = pd.merge(df1, df2, how='left', on='user_id')how="left"就是说,保留user_id字段的全部信息,不增加也不减少,但是拼接的时候只把df2表中的与df1中user_id字段交集的部分合并上就可以了,如果df2中出现了某个user_id在df1中没有出现,就抛弃掉这个样本不作处理。
自己跑个小程序,加深一下理解。可以发现,df2加到df1后,只有A0和A1的信息拼接上去了,而A4和A5因为df1里没有,故E、F、G的值都为NaN。
1.3.2 concat
用来进行简单的拼接,可以保留这些表单的全部信息。
pandas.concat(*objs*, *axis=0*, *join='outer'*, *join_axes=None*, *ignore_index=False*, *keys=None*, *levels=None*, *names=None*, *verify_integrity=False*, *copy=True*)
参数axis=1表示列拼接,axis=0表示行拼接。
比如把df1和df2的数据按列拼接起来成一个大的Dataframe,如下:
frames = [df1, df2] pd.concat(frames, axis = 1)
其实,我们经常要把训练集和测试集concat起来一起进行处理,用到的频率比较高,所以这里单独列出来。
1.3.3 其他
此外好像还有append,join,concatenate,用到了再补充。
train.drop('PassengerId',axis=1, inplace=True)
很常用的函数drop,就是去掉某一列,生成新dataframe。
1.4 预设数据
datasets里有一些预设的数据,可以方便我们进行模型的学习,比如很多教程用到的iris花的数据:
iris = datasets.load_iris()
二、数据总体预览
2.1 一些基本操作
train.head(5)
读取前5行数据,对数据有个直观了解。
train.info()
会对每一列的属性进行统计,包括名词、个数、是否为null、数据类型(int、float、object等)
这里数据个数很重要,可以直观看出是否有数据的缺失。
数据类型也很重要,涉及到后续的一些处理操作。
train.columns
输出列名称,相当于上一步的简化版,用在数据维度较多的地方,看起来比较方便。
train.describe()
会给出数值型数据的一些信息。比如个数、均值、std、min、max、25%、50%、75%。到了这一步往往能可以对一些特征的分布得出一些初步结论。
train['Survived'].value_counts()
统计特征(这里举例Survived这个特征,下同)里的各种值,包括数值型和object型,并列表。
train.drop('PassengerId',axis=1).corr()
corr函数,给出了数值型协方差,能了解数据间的相关性,大于0是正相关,小于0的负相关。理论上说,特征间相关度太高,可能会后面模型训练出来过拟合。从这里就可以对数据进行初步筛选。
特征PassengerId,是用户ID,由人脑经验得出,这应该与别的特征没有任何关系,故直接先去掉。
同时这个函数,也是绘制heatmap的前置函数,后面会讲到heatmap。
df.groupby(['key1']).size()
按key1的值分组,并统计个数。
df.groupby(['key1','key2']).size()
按'key1','key2'两列分组,并统计个数。
train.groupby(['Pclass'])['Pclass','Survived'].mean()
按Pclass分组后,统计分组下的Pclass和Survived的平均值。比较经典的用法是,分组后,可以画柱状图,来直观显示数据。
df['data1'].astype(float)
将data1列数据进行类型转换成float型。
df['add'] = ['AA','BB',"CC",'DD','EE']
直接追加一列数据叫做add的数据,好像只要不重名即可,右边为增加的数据。比如,测试集里可能没有标签列,我们直接加上一列标签列,再与训练集合并。
三、数据初步分析
画图能往往更直观表现数据的特点。因此我们需要借助一些工具。
3.1 一些绘图工具总结
3.1.1 heatmap
a = plt.subplots(figsize=(20, 12))#调整画布大小 a = sns.heatmap(train_corr, vmin=-1, vmax=1, annot=True, square=True)#画热力图 annot=True 显示系数
这里的train_corr,是上面讲到的数值型协方差,它作为绘制heatmap里需要导入的最重要的参数。
有时候,特征维度太多,heatmap看起来太复杂了。我们可以选择和标签相关度最高的前n个项,再绘制热力图。
# 寻找K个最相关的特征信息 k = 10 # number of variables for heatmap cols = train_corr.nlargest(k, 'SalePrice')['SalePrice'].index cm = np.corrcoef(train[cols].values.T) sns.set(font_scale=1.5) hm = plt.subplots(figsize=(20, 12))#调整画布大小 hm = sns.heatmap(cm, cbar=True, annot=True, square=True, fmt='.2f', annot_kws={'size': 10}, yticklabels=cols.values, xticklabels=cols.values) #annot_kws,当annot为True时,可设置各个参数,包括大小size,颜色color,加粗,斜体字等 #fmt,格式设置 这里保留2位小数 plt.show()
颜色越深,说明相关度越低。
然后,heatmap的全部参数如下,大部分弄懂就能够绘制出自己想要的图像啦。seaborn.heatmap(data, vmin=None, vmax=None, cmap=None, center=None, robust=False, annot=None, fmt='.2g', annot*kws=None, linewidths=0, linecolor='white', cbar=True, cbar*kws=None, cbar_ax=None, square=False, ax=None, xticklabels=True, yticklabels=True, mask=None, **kwargs)
关于heatmap的其他系数,这篇写的好,附上链接。
3.1.2 柱状图
train[['Pclass','Survived']].groupby(['Pclass']).mean().plot.bar()
先按Pclass分类,然后统计Survived均值,并画出柱状图。其实就是在之前分组求玩平均值后,直接添加.plot.bar(),就能绘制出柱状图啦。
这里遇到的一个情况,是我在jupyter notebook里绘制图像,发现里面的中文是乱码,查了下原因,发现得加上下面这两行,愉快解决,记录一下。如果大家有一样的情况,请效仿。
#输入下段2行代码 否则输出的图内中文为乱码 plt.rcParams['font.sans-serif']=['SimHei'] plt.rcParams['axes.unicode_minus']=False data_train.Survived.value_counts().plot(kind='bar')# 柱状图 plt.title("获救情况 (1为获救)") # 标题 plt.ylabel("人数")
这里是把bar,作为plot函数里参数的一种,直接绘制出柱状图,也是可以的。
按类统计人数,并绘制柱状图
3.1.3 普通的描点图
data_train.groupby(['Age'])['Survived'].mean().plot()
plot没有设置参数,默认是这样把各个点粗暴地连在一起,可视化效果比较差。这里显示是年龄和获救比例对应图,好像看不出太多信息。
data_train.Age[data_train.Pclass == 1].plot(kind='kde') data_train.Age[data_train.Pclass == 2].plot(kind='kde') data_train.Age[data_train.Pclass == 3].plot(kind='kde') plt.xlabel(u"年龄")# plots an axis lable plt.ylabel(u"密度") plt.title(u"各等级的乘客年龄分布") plt.legend((u'头等舱', u'2等舱',u'3等舱'),loc='best') # sets our legend for our graph.
按照年龄为横轴,并按Pclass分类,画图。
这里plot里的参数kind设定的是kde,密度曲线。从图中形象看出3种船舱里,年龄的分布,你看头等舱里油腻的中年人明显是比较多的~
3.1.4 多变量作图
#SalePrice 和相关变量之间的散点图 sns.set() cols = ['SalePrice', 'OverallQual', 'GrLivArea','GarageCars', 'TotalBsmtSF', 'FullBath', 'YearBuilt'] sns.pairplot(train[cols], size = 2.5) plt.show();
这个是我在别人code里发现的,画出两两变量之间的散点图,简直不要太屌!比如这里就是7x7的对比关系,竟恐怖如斯!好评。
3.1.5 其他与补充
其实还有个散点图scatter挺重要的,懒得画了,这里就提一下。
关于其他seaborn操作看这个链接吧。
关于plot更多参数,看这个链接吧。
对于其他很有用的数据预处理代码和绘图工具,请在下方评论,并给出代码,最好还有效果图,我会在上方添加,感谢。
四、参考资料:
https://blog.csdn.net/chixujo...