pyspark之MLlib学习【数据统计】(2)

pyspark系列文章是本人根据《PySpark实战指南》学习pyspark中学习笔记,这本书是一本译文,有些地方感觉有点小问题,不过在本人的这些笔记中都是亲自测试跑通后的小例子。仅作参考和学习。

在前一篇文章中,我们已经清理我们的原始数据,本文将了解数据的各种统计信息。

1.基本统计

在spark的DataFrame中通过.discribe()方法实现数据的各种统计信息,但在使用MLib时则采用.colStats()方法。该方法使用RDD的数据来计算MultivariateStatisticalSummary对象的描述性统计信息,并返回MultivariateStatisticalSummary

  • count():行数
  • max():列中的最大值
  • mean():列中所有值的平均值
  • min():列中的最小值
  • normL1():列中值的L1-Norm值
  • normL2():列中值的L2-Norm值
  • numNonzeros():列中非零值的数量
  • variance():列中值的方差
  • ......
#计算数字特征的统计特性
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.相关性

相关性有助于识别特征之间的关联性。下面我们将检查前面数据的性关系。

  • 计算相关性矩阵,且只打印相关系数大于5的特征。

#计算相关性,且只打印相关系数大于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

你可能感兴趣的:(spark)