数据分析小实验(下)

目录

    一、数据准备

    二、缺失值处理

    三、清洗数据

    四、聚类分析

    五、结果评估与分析

三、清洗数据

    对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


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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值