pyspark系列文章是本人根据《PySpark实战指南》学习pyspark中学习笔记,这本书是一本译文,有些地方感觉有点小问题,不过在本人的这些笔记中都是亲自测试跑通后的小例子。仅作参考和学习。
在前一篇文章中,我们已经清理我们的原始数据,本文将了解数据的各种统计信息。
1.基本统计
在spark的DataFrame中通过.discribe()方法实现数据的各种统计信息,但在使用MLib时则采用.colStats()方法。该方法使用RDD的数据来计算MultivariateStatisticalSummary对象的描述性统计信息,并返回MultivariateStatisticalSummary
#计算数字特征的统计特性 import pyspark.mllib.stat as st import numpy as np numeric_cols = ['MOTHER_AGE_YEARS','FATHER_COMBINED_AGE', 'CIG_BEFORE','CIG_1_TRI','CIG_2_TRI','CIG_3_TRI', 'MOTHER_HEIGHT_IN','MOTHER_PRE_WEIGHT', 'MOTHER_DELIVERY_WEIGHT','MOTHER_WEIGHT_GAIN'] numeric_rdd = births_transformed.select(numeric_cols).rdd.map(lambda row: [e for e in row]) mllib_stats = st.Statistics.colStats(numeric_rdd) for col,m,v in zip(numeric_cols,mllib_stats.mean(),mllib_stats.variance()): print ('{0}: \t {1:.2f} \t {2:.2f}'.format(col,m,np.sqrt(v)) )
MOTHER_AGE_YEARS: 28.30 6.08 FATHER_COMBINED_AGE: 44.55 27.55 CIG_BEFORE: 1.43 5.18 CIG_1_TRI: 0.91 3.83 CIG_2_TRI: 0.70 3.31 CIG_3_TRI: 0.58 3.11 MOTHER_HEIGHT_IN: 65.12 6.45 MOTHER_PRE_WEIGHT: 214.50 210.21 MOTHER_DELIVERY_WEIGHT: 223.63 180.01 MOTHER_WEIGHT_GAIN: 30.74 26.23从结果中我们可以看出:与父亲相比,母亲的年龄更小:母亲的平均年龄是28岁,而父亲的平均年龄则超过44岁;且许多母亲怀孕后开始戒烟了(这对宝宝来说是一个好的现象);而令人吃惊的是,有些母亲在怀孕后仍持续吸烟。
对于分类变量,我们将计算其值的频率:
#查看分类变量的统计特性 categorical_cols = [e for e in births_transformed.columns if e not in numeric_cols] categorical_rdd = births_transformed.select(categorical_cols).rdd.map(lambda row : [e for e in row]) for i,col in enumerate(categorical_cols): agg = categorical_rdd.groupBy(lambda row:row[i]).map(lambda row :(row[0],len(row[1]))) print (col,sorted(agg.collect(),key=lambda e1:e1[1],reverse=True))
('INFANT_ALIVE_AT_REPORT', [(1, 23349), (0, 22080)]) ('BIRTH_PLACE', [(u'1', 44558), (u'4', 327), (u'3', 224), (u'2', 136), (u'7', 91), (u'5', 74), (u'6', 11), (u'9', 8)]) ('DIABETES_PRE', [(0, 44881), (1, 548)]) ('DIABETES_GEST', [(0, 43451), (1, 1978)]) ('HYP_TENS_PRE', [(0, 44348), (1, 1081)]) ('HYP_TENS_GEST', [(0, 43302), (1, 2127)]) ('PREV_BIRTH_PRETERM', [(0, 43088), (1, 2341)])从结果中可以看出,大部分的生产是在医院里(BIRTH_PLACE为1);大约550例的生产是在家中:其中有些是计划好的(BIRTH_PLACE为3),而有些不是(BIRTH_PLACE为4)
2.相关性
相关性有助于识别特征之间的关联性。下面我们将检查前面数据的性关系。
#计算相关性,且只打印相关系数大于0.5的特征 corrs = st.Statistics.corr(numeric_rdd) for i ,e1 in enumerate(corrs>0.5): correlated = [ (numeric_cols[j],corrs[i][j])for j,e in enumerate(e1) if e == 1.0 and j != i ] if len(correlated)>0: for e in correlated: print ('{0}-to-{1}: {2:.2f}'.format(numeric_cols[i],e[0],e[1]))
CIG_BEFORE-to-CIG_1_TRI: 0.83 CIG_BEFORE-to-CIG_2_TRI: 0.72 CIG_BEFORE-to-CIG_3_TRI: 0.62 CIG_1_TRI-to-CIG_BEFORE: 0.83 CIG_1_TRI-to-CIG_2_TRI: 0.87 CIG_1_TRI-to-CIG_3_TRI: 0.76 CIG_2_TRI-to-CIG_BEFORE: 0.72 CIG_2_TRI-to-CIG_1_TRI: 0.87 CIG_2_TRI-to-CIG_3_TRI: 0.89 CIG_3_TRI-to-CIG_BEFORE: 0.62 CIG_3_TRI-to-CIG_1_TRI: 0.76 CIG_3_TRI-to-CIG_2_TRI: 0.89 MOTHER_PRE_WEIGHT-to-MOTHER_DELIVERY_WEIGHT: 0.54 MOTHER_PRE_WEIGHT-to-MOTHER_WEIGHT_GAIN: 0.65 MOTHER_DELIVERY_WEIGHT-to-MOTHER_PRE_WEIGHT: 0.54 MOTHER_DELIVERY_WEIGHT-to-MOTHER_WEIGHT_GAIN: 0.60 MOTHER_WEIGHT_GAIN-to-MOTHER_PRE_WEIGHT: 0.65 MOTHER_WEIGHT_GAIN-to-MOTHER_DELIVERY_WEIGHT: 0.60从结果中可以看出“CIG_...”的相关特征是高度相关的。由于我们要预测婴儿的生存几率,所以我们只会保留“CIG_1_TR1"特征,且重量特征也是高度相关的,在此我们只会保留“MOTHER_PRE_WEIGHT”
#需要保留的特征 features_to_keep = [ 'INFANT_ALIVE_AT_REPORT', 'MOTHER_AGE_YEARS', 'FATHER_COMBINED_AGE', 'CIG_1_TRI', 'MOTHER_HEIGHT_IN', 'MOTHER_PRE_WEIGHT', 'DIABETES_PRE', 'DIABETES_GEST', 'HYP_TENS_PRE', 'HYP_TENS_GEST', 'PREV_BIRTH_PRETERM' ], births_transformed = births_transformed.select([e for e in features_to_keep])3.统计测试
我们无法计算分类特征的相关性。然而,我们可以进行卡方检验来确定是否存在显著差异。
import pyspark.mllib.linalg as ln for cat in categorical_cols[1:]: agg = births_transformed.groupBy('INFANT_ALIVE_AT_REPORT').pivot(cat).count() agg_rdd = agg.rdd.map(lambda row: [0 if e == None else e for e in row]).collect() row_length = len(agg.collect()[0]) -1 agg = ln.Matrices.dense(row_length,2,agg_rdd) test = st.Statistics.chiSqTest(agg) print cat,round(test.pValue,4) spark.stop()循环遍历所有的分类变量,并通过“INFANT_ALIVE_AT_REPORT”特征进行转换,以获取计数。接下来,我们将其转换为RDD,因此我们可以使用pyspark.mllib.linalg模块
将它们转换成矩阵。
.Matrices.dende()方法的第一个参数指定矩阵的行数,本例子中是分类特征的不同值的长度;第二个参数是指列数,因为我们的“INFANT_ALIVE_AT_REPORT”目标变量只有两个值,所以列为二;最后一个参数是要转换为矩阵的值的列表。
例如:
print (ln.Matrices.dense(3,2,[1,2,3,4,5,6]))
DenseMatrix([[ 1., 4.], [ 2., 5.], [ 3., 6.]])
一旦我们以矩阵的形式存放我们的计数,那么我们可以使用.chiSqTest()方法来计算我们需要的结果。
BIRTH_PLACE 0.0 DIABETES_PRE 0.0 DIABETES_GEST 0.0 HYP_TENS_PRE 0.0 HYP_TENS_GEST 0.0 PREV_BIRTH_PRETERM 0.0