前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >数据分析小实验(下)

数据分析小实验(下)

作者头像
智能算法
发布2018-04-03 11:28:01
1.1K0
发布2018-04-03 11:28:01
举报
文章被收录于专栏:智能算法

目录

一、数据准备

二、缺失值处理

三、清洗数据

四、聚类分析

五、结果评估与分析

三、清洗数据

对categorical data特征进行观察。发现很多特征属于偏态分布或分类太多,对于我们进行分析是非常不利的,因此需要对部分数据合并。

1)workclass

在进行合并时。一些和我们分析的目标相关的关键信息是需要单独保留的。比如self-employed,对于评估个人收入高低很有帮助。其他的部分选择合并。

government_jobs = df.workclass.str.endswith('-gov')

df.loc[government_jobs,'workclass'] = 'Government'

others = df.workclass.isin(['Retired','Without-pay','Never-worked','Unknown'])

df.loc[others,'workclass'] = 'Other'

df.workclass = df.workclass.replace({"Self-emp-not-inc":"Freelance","Self-emp-inc":"Proprietor"})

2)对education分析

学校教育对于个人的收入还是有比较大的影响的,但是7th-8th和9th似乎差别不太,这里就需要对于美国教育有一定的了解才能够准备的对结果合并。我们将学校教育划分为三类,Primary, Secondary, Tertiary等三类。

primary = df.education.isin(['Preschool', '1st-4th', '5th-6th'])

df.loc[primary,'education'] = 'Primary'

secondary = df.education.isin(['Some-college', '11th', '9th', '7th-8th', '10th','12th','HS-grad','Assoc-voc'])

df.loc[secondary,'education'] = 'Secondary'

teriary = df.education.isin(['Bachelors', 'Masters', 'Doctorate', 'Prof-school','Assoc-acdm'])

df.loc[teriary,'education'] = 'Tertiary'

划分后结果如下:

3)maritalstatus婚姻状况

婚姻状态基本可以合并成已婚,未婚就可以了,并用数字0,1表示就可以了。

df.maritalstatus = (df.maritalstatus != 'Never-married').astype(int)

4)occupation职业

个人的工作对于收入的高低是相关性很高的特征, 因此划分职业按潜在收入高低划分,我们先对职业和收入进行对比。

income_per_occupation = df[['occupation','income']].groupby('occupation').income.value_counts().unstack()

但是只观察上面的关系图并不能很好的帮助我们直接对职业划分,需要进一步观察高收入人群的占比情况,因此通过下面:

income_per_occupation = (income_per_occupation.large / income_per_occupation.sum(1)).sort_values(ascending=False)

得到结果如下:

可以按高收入占比进行划分,将占比大于0.33归为high,(0.2,0.33)归为med,小于等于0.2的归为low

high_earnings = df.occupation.isin(income_per_occupation[income_per_occupation >= 0.33].index.tolist())

df.loc[high_earnings,'occupation'] = 'High'

mid_earnings = df.occupation.isin(income_per_occupation[(income_per_occupation > 0.20) & (income_per_occupation < 0.33)].index.tolist())

df.loc[mid_earnings,'occupation'] = 'Med'

low_earnings = df.occupation.isin(income_per_occupation[income_per_occupation <= 0.20].index.tolist())

df.loc[low_earnings,'occupation'] = 'Low'

接下来剩下None值,由于数量少,将它归到Med中。

5)relationship

对收入高低的影响关系来看,身份是Husband或Wife还是比较重要的,而且各自的市场价值也不相同,根据一份报告,将消费投资和市场价值人群划分如下:少女>儿童>少妇>老人>狗>男人。Husband和Wife,这个特征更像是将性别和婚姻状态的混合,或许可以考虑对婚姻状态的验证和填充使用。下面观察一下‘Own-Child’和年龄的关系

通过分布结果看的话,并不是直觉意义上拥有小孩的情况,如果是拥有小孩的话,应该是随着年龄的增长而增长才对。应该30岁之前的未婚的占多数。因此对于会不会影响个人收入或潜在价值,很难说。那么对于‘Not-in-family’、‘Own-child’、'Unmarried'和'Other-relative' 四个就归为‘Other了’。

或者如果愿意的话,划分为Husband、Wife,unmarried和other也是可以的,其实本来就没有所谓的准确答案,具体哪个更优,可以通过聚类效果来抉择。

not_spouse = df.relationship.isin(['Not-in-family', 'Own-child', 'Unmarried', 'Other-relative'])

df.loc[not_spouse, 'relationship'] = 'Other'

再看效果:

6)race种族

乍一看,白人遥遥领先啊,对个两两合并的方式肯定也不凑效了,只能直接将race划分为white和非white了。 df.race = (df.race == 'White').astype(int)。

对于sex特征,只有Male和Female,不需要做任何的处理,可以直接用了。

7)nativecountry

USA又是一巨无霸,而且涉及到很多的国家,如果简单的将结果分为USA和非USA,肯定会错失很多关键信息,毕竟国家的发展状况还是会影响到个人收入的,因此可以将国家GDP考虑进来,将GDP按高低分段。或按发达国家,发展中国家和贫穷国家划分都是可选的方案的。嗯,这就交给你们去实践了,实验就按USA和非USA来了。

df.nativecountry = (df.nativecountry == 'United-States').astype(int) 。Categorical的清理工作已经完成,还剩下最关键的income和continuous没有处理了。

8) continuous连续变量

特征中出现连续变量的有三个,hoursperweek,capitalgain,capitalloss等三个,由于hoursperweek中40小时占比还挺大,可以考虑按40小时,小于40小时,大于40小时方式划分三段。或者将结果做归一化到[0,1],然后直接使用特征。

而capitalgain,capitalloss出现严重的偏态分布。而且非常的稀疏,需要确定一下是否存在使用价值。

将capitalgain,capitalloss放在一起比较,看是否存在某种关系。

果然,两个更像是一个特征,因为一个人不可能同时收益和损失,所有的点都在数轴上。可以考虑将两个特征合并成新的特征,has_capital_account, has_losses, has_gains。

处理好之后的数据如下:

是不是以为就结束了,但是还有一步没做,目前的结果并不能直接放到模型中,还需对特征,转变哑变量,利用pd.get_dummies处理。还有将目前income处理成is_large数值类型,

df['y'] = (df.income == 'large').astype(int)

其他暂时做空值处理。我们接下来对income的空值利用RandomForest来进行预测,用预测的结果填充income空值。

from sklearn.ensemble import RandomForestClassifier as RF

from sklearn.cross_validation import cross_val_score

data = df.select_dtypes(['int','float'])

X = data[data.y.notnull()].drop('y',axis=1)

y = df.y[df.y.notnull()]

X_new = df[df.y.isnull()].select_dtypes(['int','float']).drop('y',axis=1)

cls = RF(25, n_jobs=-1)

cross_val_score(cls,X,y,'roc_auc',cv=5)

打印出结果[ 0.8726842 , 0.86185507, 0.86925446, 0.87965868, 0.87036015],效果还不错。接下来对空值进行预测。

cls = RF(25, n_jobs=-1)

cls.fit(X,y)

df.y[df.y.isnull()] = cls.predict(X_new)

接下来就是将object类型转变Categorical,float类型转变int类型。到此,数据清洗和缺失值的处理的过程就全部完成了。

四、聚类分析

在做聚类之前,需要做特征选择,选出一些和income相关性高的特征出来,再做聚类分析。这样聚类得到的结果可信度高。将特征与income做比较。下面选出一组分析。

通过比较Earning Potential,Relationship与income有强关联。将Relationship与income的占比情况分布。因此Relationship为Wife和Husband中高收入占比较高,因此与高income具有关联性,因此在聚类时,可以选为分类的特征。

类似方法,选择了如下特征:

'age','sex_male','is_married','is_white','education_tertiary','earning_potential_high','relationship_husband','relationship_wife',‘hoursperweek’

作为聚类的特征。其中需要age和hoursperweek做归一化到[0,1]中。

接下来调用sklearn.cluster中的KMeans做聚类,但是做聚类之前,要考虑聚类后的结果具可解释性,能够对具体营销有指导意义,因此需要确定最大K值的选取,如果k值太大,聚类本身也就失去意义,举个极端的例子,如果每个数据本身成为一个类别呢。

但是具体的k值,选取需要按照一定指标选取,我们先选取k=2,3,4,5,6,7得到聚类。

kmeans = KMeans(k,)

kmeans.fit(X)

另外考虑实际运行环境,聚类时,随机选取10000样本来做。

五、结果评估与分析

评估的的指标是通过计算Silhouette Score,它是通过簇内距离a与簇外距离b的比,(b - a) / max(a, b),能很好的评估聚类的效果。

可以发现在k=5之后,Silhouette Score的增长减缓,因此选择k=5作为聚类的k值比较合理的选择。利用k=5重新训练模型,最后得到分类的情况如下:

2.0 2751

0.0 2603

1.0 2175

3.0 1451

4.0 1020

接下来分类后的特征对于分类:

后续对于聚类的解释,可能就需要加入具体的场景和业务背景知识了。

参考:

KMeans:http://scikit-learn.org/stable/modules/generated/sklearn.cluster.KMeans.html

Silhoutte Score:http://scikit-learn.org/stable/modules/generated/sklearn.metrics.silhouette_score.html

免责声明:本文系网络转载。版权归原作者所有。如涉及版权,请联系删除!

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2017-06-30,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 智能算法 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档