阅读《Data Science from Scratch》之统计学

对于数据分析师而言,统计学必定是一门绕不开的学科。我今生做数据科学家已经无望了,但就工程角度来讲,致力于大数据行业,了解一些必备的统计学知识仍有必要。Data Science from Scratch的第5章讲解了统计学初级知识,对于我这样的门外汉而言,可谓恰到好处。尤喜书中还给出Python的代码示例,对于程序员而言,这是了解概念知识的利器。

统计学会描述一组数据,并通过一些常用的统计运算甄别出数据的规律,从而帮助分析师能够更好地理解数据。统计学中最常见的运算自然就是计数(count)、最大值(max)、最小值(min)和平均数(mean)。

Central Tendencies

mean其实属于Central Tendencies中的一种运算。根据网站QuickMBA对Central Tendency的解释,该术语指的是对一组数据的中值计算,包括mean、median和mode。mean即求平均值,是最常见的数学运算,而median称为“中位数”,指的是最靠近中间位置的数。如果一组数据的个数为奇数,则median只有一个,否则为最靠近中间的两个值的平均数。因此,在计算median时,需要对数据进行排序。阅读代码就一目了然了:

def median(v):
    n = len(v)
    sorted_v = sorted(v)
    midpoint = n // 2

    if n % 2 == 1:
        # n is odd
        return sorted_v[midpoint]
    else:
        # n is even
        lo = midpoint - 1
        hi = midpoint
        return (sorted_v[lo] + sorted_v[hi]) / 2

mode称为“众数”,指的是在一组数据中出现次数最多的数。例如在[1,1,2,3,4,5,3]这组数据中,1和3就是mode获得的值。在Python中,提供了Counter来获得各个元素出现的次数,因此mode函数的实现非常简单:

def mode(x):
    counts = Counter(x)
    max_count = max(counts.values())
    return [x_i for x_i, count in counts.iteritems() if count == max_count]

mean和median比较而言,前者更容易受到异常数据的影响,而后者取决于位置,无论数值如何分布,基本上都不会影响到它的值。

事实上,median仅仅是quantile(分位数)的一个特化而已,它相当于第二个分位数,取值为0.5。对于quantile而言,究竟取值哪个范围,要看传入的百分比。若记该比例为q,可以称之为q-quantile。median可以记为2-quantile。以下是维基百科对各种百分比值对应术语的说明:

The only 2-quantile is called the median
The 3-quantiles are called tertiles or terciles → T
The 4-quantiles are called quartiles → Q
The 5-quantiles are called quintiles → QU
The 6-quantiles are called sextiles → S
The 10-quantiles are called deciles → D
The 12-quantiles are called duo-deciles → Dd
The 20-quantiles are called vigintiles → V
The 100-quantiles are called percentiles → P
The 1000-quantiles are called permilles → Pr

在统计学中,为了更好地分析和观测数据,通常会将数据分为多个等分,四等分为最常见的情况,处于三个分割点位置的数值就是quantile。划分后的数据有利于对各个区间段的数据进行比较。正如《Head First Data Analysis》一书所说:“进行有效地比较是数据分析的核心”,很多时候,数字需要和数字进行比较,才能产生价值。

标准差(standard deviation)

如果调用Spark中DataFrame的describe(),会显示针对DataFrame各列数据进行的summary统计,统计结果就包括前面提到的count、mean、max和min。除此之外,还包括stddev。stddev即为standard deviation(标准差)。要计算标准差,需要先计算variance(方差)。因为标准差就是针对方差求平方根:

def standard_deviation(x):
    math.sqrt(variance(x))

所谓variance,是各个数与mean差值的平方和,然后再除以这组数据的个数(或个数减一,即变异数):

def de_mean(x):
    """获得各个数与mean的差值"""
    x_mean = mean(x)
    return [x_i - x_mean for x_i in x]

def variance(x):
    n = len(x)
    deviations = de_mean(x)
    return sum_of_squares(deviations) / (n - 1)

之所以要除以n-1,而非n,是因为我们在采集样本时,求得的平均值仅仅是一个估算值,而非理想的平均值,存在一定的偏差(为了保证测量的准确性,我们希望采集的数据样本越大越好)。因此在对x_i - x_mean求平方时,会比实际的平方差要小,通过对n减一,就可以对这种偏差做校正。这一偏差在统计学中称之为Unbiased estimation of standard deviation

标准差通常用作对统计分布程度的测量,反映了一组数据的离散(dispersion)程度。为什么要使用标准差呢?原因在于一个事实,那就是我们采集的数据样本与真实值总是存在一定的偏差。现实情况下,我们甚至根本不知道这个真实值,就像现实世界根本就不存在几何学中各种标准的图形那样。所以,要测量这组数据的离散程度,最好的测量方法是让这些数据更加紧密地分散到真实值周围。否则距离越大,准确性就越差。这就是所谓的Dispersion(离散度)。最常见的离散度量化方式就是range(极差),即计算最大值与最小值的差值。然而对于一组数据而言,仅仅依靠两个值来评判数据的离散度,显然是极不准确的。我们可以想象这些数据其实是在二维平面上的各个点。那么平均数就是介于这些点之间的其中一个点,它与大多数点之间的连线距离相对均匀。因此,一个直观的测量方法是计算各个数据与平均值之间的差。将这些差值累加起来(称之为“deviation from mean,离均差”),就可以反映一个较为准确的离散程度。该值越大,说明离散度越大,分布的区间也越大。然而,这些数据可能大于平均值,也可能小于平均值,导致差值有正有负。对于一些分布极为离散的数据,在特殊情况下,甚至可能得到的离均差为0,或者接近于0,导致非常糟糕的误差。

要避免这种正负相加的问题,可以对差值求平方(另一种办法是求绝对值)。这就是variance的基本思路。但是平方值实际上扩大了数据与平均值的差值,为保证测量的准确性,就需要对variance求一次平方根来压缩这种差值,于是就获得了standard deviation(标准差)。在统计分析中,如果需要计算两组或多组数据之间的相关度(correlation),就会使用到标准差。我将在下一篇博客中继续学习这部分知识。

2015-08-14 22:2759数据科学