数据探索之统计分布

本文用Python统计模拟的方法,介绍四种常用的统计分布,包括离散分布:二项分布和泊松分布,以及连续分布:指数分布和正态分布,最后查看人群的身高和体重数据所符合的分布。

# 导入相关模块
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
%matplotlib inline
%config InlineBackend.figure_format = 'retina'

随机数

计算机发明后,便产生了一种全新的解决问题的方式:使用计算机对现实世界进行统计模拟。该方法又称为“蒙特卡洛方法(Monte Carlo method)”,起源于二战时美国研制原子弹的曼哈顿计划,它的发明人中就有大名鼎鼎的冯·诺依曼。蒙特卡洛方法的名字来源也颇为有趣,相传另一位发明者乌拉姆的叔叔经常在摩洛哥的蒙特卡洛赌场输钱,赌博是一场概率的游戏,故而以概率为基础的统计模拟方法就以这一赌城命名了。

使用统计模拟,首先要产生随机数,在Python中,numpy.random 模块提供了丰富的随机数生成函数。比如生成0到1之间的任意随机数:

np.random.random(size=5)  # size表示生成随机数的个数
array([ 0.32392203,  0.3373342 ,  0.51677112,  0.28451491,  0.07627541])

又比如生成一定范围内的随机整数:

np.random.randint(1, 10, size=5)  # 生成5个1到9之间的随机整数
array([5, 6, 9, 1, 7])

计算机生成的随机数其实是伪随机数,是由一定的方法计算出来的,因此我们可以按下面方法指定随机数生成的种子,这样的好处是以后重复计算时,能保证得到相同的模拟结果。

np.random.seed(123)

在NumPy中,不仅可以生成上述简单的随机数,还可以按照一定的统计分布生成相应的随机数。这里列举了二项分布、泊松分布、指数分布和正态分布各自对应的随机数生成函数,接下来我们分别研究这四种类型的统计分布。

  • np.random.binomial()
  • np.random.poisson()
  • np.random.exponential()
  • np.random.normal()

二项分布

二项分布n个独立的是/非试验中成功的次数的概率分布,其中每次试验的成功概率为p。这是一个离散分布,所以使用概率质量函数(PMF)来表示k次成功的概率:

最常见的二项分布就是投硬币问题了,投n次硬币,正面朝上次数就满足该分布。下面我们使用计算机模拟的方法,产生10000个符合(n,p)的二项分布随机数,相当于进行10000次实验,每次实验投掷了n枚硬币,正面朝上的硬币数就是所产生的随机数。同时使用直方图函数绘制出二项分布的PMF图。

def plot_binomial(n,p):
    '''绘制二项分布的概率质量函数'''
    sample = np.random.binomial(n,p,size=10000)  # 产生10000个符合二项分布的随机数
    bins = np.arange(n+2) 
    plt.hist(sample, bins=bins, align='left', normed=True, rwidth=0.1)  # 绘制直方图
    #设置标题和坐标
    plt.title('Binomial PMF with n={}, p={}'.format(n,p))  
    plt.xlabel('number of successes')
    plt.ylabel('probability')
    

plot_binomial(10, 0.5)

投10枚硬币,如果正面或反面朝上的概率相同,即p=0.5, 那么出现正面次数的分布符合上图所示的二项分布。该分布左右对称,最有可能的情况是正面出现5次。

但如果这是一枚作假的硬币呢?比如正面朝上的概率p=0.2,或者是p=0.8,又会怎样呢?我们依然可以做出该情况下的PMF图。

fig = plt.figure(figsize=(12,4.5)) #设置画布大小
p1 = fig.add_subplot(121)  # 添加第一个子图
plot_binomial(10, 0.2)
p2 = fig.add_subplot(122)  # 添加第二个子图
plot_binomial(10, 0.8)

这时的分布不再对称了,正如我们所料,当概率p=0.2时,正面最有可能出现2次;而当p=0.8时,正面最有可能出现8次。

泊松分布

泊松分布用于描述单位时间内随机事件发生次数的概率分布,它也是离散分布,其概率质量函数为:

比如你在等公交车,假设这些公交车的到来是独立且随机的(当然这不是现实),前后车之间没有关系,那么在1小时中到来的公交车数量就符合泊松分布。同样使用统计模拟的方法绘制该泊松分布,这里假设每小时平均来6辆车(即上述公式中lambda=6)。

lamb = 6
sample = np.random.poisson(lamb, size=10000)  # 生成10000个符合泊松分布的随机数
bins = np.arange(20)
plt.hist(sample, bins=bins, align='left', rwidth=0.1, normed=True) # 绘制直方图
# 设置标题和坐标轴
plt.title('Poisson PMF (lambda=6)')
plt.xlabel('number of arrivals')
plt.ylabel('probability')
plt.show()

指数分布

指数分布用以描述独立随机事件发生的时间间隔,这是一个连续分布,所以用质量密度函数表示:

比如上面等公交车的例子,两辆车到来的时间间隔,就符合指数分布。假设平均间隔为10分钟(即1/lambda=10),那么从上次发车开始,你等车的时间就满足下图所示的指数分布。

tau = 10
sample = np.random.exponential(tau, size=10000)  # 产生10000个满足指数分布的随机数
plt.hist(sample, bins=80, alpha=0.7, normed=True) #绘制直方图
plt.margins(0.02) 

# 根据公式绘制指数分布的概率密度函数
lam = 1 / tau
x = np.arange(0,80,0.1)
y = lam * np.exp(- lam * x)
plt.plot(x,y,color='orange', lw=3)

#设置标题和坐标轴
plt.title('Exponential distribution, 1/lambda=10')
plt.xlabel('time')
plt.ylabel('PDF')
plt.show()

正态分布

正态分布是一种很常用的统计分布,可以描述现实世界的诸多事物,具备非常漂亮的性质,我们在下一讲参数估计之中心极限定理时会详细介绍。其概率密度函数为:

以下绘制了均值为0,标准差为1的正态分布的概率密度曲线,其形状好似一口倒扣的钟,因此也称钟形曲线。

def norm_pdf(x,mu,sigma):
    '''正态分布概率密度函数'''
    pdf = np.exp(-((x - mu)**2) / (2* sigma**2)) / (sigma * np.sqrt(2*np.pi))
    return pdf

mu = 0    # 均值为0
sigma = 1 # 标准差为1

# 用统计模拟绘制正态分布的直方图
sample = np.random.normal(mu, sigma, size=10000)
plt. hist(sample, bins=100, alpha=0.7, normed=True)

# 根据正态分布的公式绘制PDF曲线
x = np.arange(-5, 5, 0.01)
y = norm_pdf(x, mu, sigma)
plt.plot(x,y, color='orange', lw=3)
plt.show()

身高、体重的分布

以上从计算机模拟的角度出发,介绍了四种分布,现在让我们看一下现实中的数据分布。继续上一讲数据探索之描述性统计中使用的BRFSS数据集,我们查看其中的身高和体重数据,看看他们是不是满足正态分布。

首先导入数据,并编写绘制PDF和CDF图的函数 plot_pdf_cdf(),便于重复使用。

# 导入BRFSS数据
import brfss
df = brfss.ReadBrfss()
height = df.height.dropna()
weight = df.weight.dropna()
def plot_pdf_cdf(data, xbins, xrange, xlabel):
    '''绘制概率密度函数PDF和累积分布函数CDF'''
    
    fig = plt.figure(figsize=(16,5)) # 设置画布尺寸

    p1 = fig.add_subplot(121)  # 添加第一个子图
    # 绘制正态分布PDF曲线
    std = data.std()
    mean = data.mean()
    x = np.arange(xrange[0], xrange[1], (xrange[1]-xrange[0])/100)
    y = norm_pdf(x, mean, std)
    plt.plot(x,y, label='normal distribution')
    # 绘制数据的直方图
    plt.hist(data, bins=xbins, range=xrange, rwidth=0.9, 
             alpha=0.5, normed=True, label='observables')
    # 图片设置
    plt.legend()
    plt.xlabel(xlabel)
    plt.title(xlabel +' PDF')

    p2 = fig.add_subplot(122)  #添加第二个子图
    # 绘制正态分布CDF曲线
    sample = np.random.normal(mean, std, size=10000)
    plt.hist(sample, cumulative=True, bins=1000, range=xrange, 
             normed=True, histtype='step', lw=2, label='normal distribution')
    # 绘制数据的CDF曲线
    plt.hist(data, cumulative=True, bins=1000, range=xrange, 
             normed=True, histtype='step', lw=2, label='observables')
    #图片设置
    plt.legend(loc='upper left')
    plt.xlabel(xlabel)
    plt.title( xlabel + ' CDF')
    plt.show()

人群的身高分布比较符合正态分布。

plot_pdf_cdf(data=height, xbins=21, xrange=(1.2, 2.2), xlabel='height')

但是体重分布明显右偏,与对称的正态分布存在一定的差异。

plot_pdf_cdf(data=weight, xbins=60, xrange=(0,300), xlabel='weight')

将体重数据取对数值后,其分布就与正态分布非常吻合。

log_weight = np.log(weight)
plot_pdf_cdf(data=log_weight, xbins=53, xrange=(3,6), xlabel='log weight')

本文代码github

数据探索系列目录:

  1. 开篇:数据分析流程
  2. 描述性统计分析
  3. 统计分布(本文)
  4. 参数估计
  5. 假设检验

参考资料:

致谢:
最后还是非常感谢解密大数据社群的小伙伴们给我的支持和鼓励,让我们一起成长。


解密大数据社群公号
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,222评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,455评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,720评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,568评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,696评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,879评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,028评论 3 409
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,773评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,220评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,550评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,697评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,360评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,002评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,782评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,010评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,433评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,587评论 2 350

推荐阅读更多精彩内容