对于一维数据的可视化,直方图(Histogram)与核密度估计(Kernel Density Estimates)可以很好的表示各个数据值的概率分布,但在表示数据累积分布上这两种方法就无能为力了。数据的累积分布,也即小于等于当前数据值的所有数据的概率分布,对于表示数据点在某个区间内出现的概率有很大的帮助。从数学上来说,累积分布函数(Cumulative Distribution Function,简称CDF)是概率分布函数的积分;而在绘制累积分布函数的时候,由于真实的概率分布函数未知,因此往往定义为直方图分布的积分:

1.累积分布函数(CDF)的使用

以-4到4之间分布的10000个数据点为例,绘制成直方图与核密度估计是这样的:

这两张图可以很好的表示-4到4之间任意数据值的概率大小,但是在回答下面几个问题的时候就比较困难了:

所有大于2的数据点在总数据集中所占比例约有多大?

所有大于1.3而小于2的数据点在总数据集中所占比例是多少?

在上述例子中,数据集大致遵循正态分布,因此从直方图或核密度估计的结果中推测这两个问题的答案还是可能的;但是对于不规则的概率分布曲线来说,这样做就基本上行不通了。回答上述问题的通用方法是绘制累积分布函数图:

根据这张累积分布函数图,可以很方便地回答之前的两个问题:

CDF中横轴上的2对应的Y值约为0.98,因此所有大于2的数据点所占比例约为2%。

CDF中横轴上的1.3对应的Y值约为0.75,因此所有介于1.3和2之间的数据点所占比例约为23% (0.98-0.75)。

与直方图、核密度估计相比,累积分布函数存在以下几个特点:

累积分布函数是X轴单调递增函数。

累积分布函数更加平滑,图像中噪音更小。

累积分布函数没有引入带宽等外部概念,因此不会丢失任何数据信息。对于给定的数据集,累积分布函数是唯一的。

累积分布函数一般都经过归一化处理,单调递增且趋近于1。

2.python如何实现

import numpy as np
import statsmodels.api as sm
import matplotlib.pyplot as plt


data=[14.27,14.80,12.28,17.09,15.10,12.92,15.56,15.38,
      15.15,13.98,14.90,15.91,14.52,16,16,16,
      13.98,14.47,14.65,14.73,15.18,16,16,16,
      15.40,14.68,13.33,14.41,14.19,15.21,14.75,14.41,
      14.04,13.68,12,14.32,13.64,14.77,14.30,14.62,
      14.10,15.47,13.73,13.65,15.02,14.01,14.92,15.47,
      13.75,14.87,15.28,14.43,13,14.57,15.49,15.13,13,13,13]
ecdf = sm.distributions.ECDF(data)
x = np.linspace(min(data), max(data))
y = ecdf(x)


data2=[12,14.80,12.28,17.09,15.10,12.92,15.56,15.38,
      15.15,13.98,14.90,15.91,14.52,15.63,13.83,13.66,
      13.98,14.47,14.65,14.73,15.18,14.49,14.56,15.03,
      15.40,14.68,13.33,14.41,14.19,15.21,14.75,14.41,
      14.04,13.68,15.31,14.32,13.64,14.77,14.30,14.62,
      14.10,15.47,13.73,13,15.02,14.01,14.92,15.47,
      13.75,14.87,15.28,13,13.96,14.57,15.49,15.13,
      14.23,14.44,14.57]
ecdf = sm.distributions.ECDF(data2)
x2 = np.linspace(min(data2), max(data2))

#for a, b in zip(x, y):
#    print(a, b)

plt.grid(True)

plt.plot(x, y, linewidth='3', label='ICN', color="blue", linestyle=":")
plt.plot(x2, y2, linewidth='3', label='RL-ICN-CC', color="red", linestyle="--")
plt.xlabel('Throughput (×10 Mb/s)', fontsize=15)
plt.ylabel('CDF', fontsize=15)

plt.xlim(12,17)
plt.ylim(0, 1)

plt.xticks(fontsize=15)
plt.yticks(fontsize=15)
plt.legend(loc="lower right",fontsize = 15)#也可强制位置,增加:loc="lower right"
plt.show()