分享

生物统计(7)——R中dnorm, pnorm, qnorm与rnorm的区别

 微笑如酒 2018-09-13

前言

这是一篇译文,原文对R与分布有关的几个函数进行了介绍。

我们知道,在R中,与正态分布(或者说其它分布)有关的函数有四个,分别为dnorm,pnorm,qnorm和rnorm,其中,dnorm表示密度函数,pnorm表示分布函数,qnorm表示分位数函数,rnorm表示生成随机数的函数。在R中与之类似的函数还有很多,具体的可以通过help(Distributions)命令去查看,对于分位数或百分位数的一些介绍可以看这篇笔记《分位数及其应用》,关于正态分布的知识可以看这篇笔记《正态分布笔记》

现在这篇笔记就介绍一下这些函数的区别。

dnorm

dnorm中的d表示densitynorm表示正态贫,这个函数是正态分布的概率密度(probability density)函数

正态分布的公式如下所示:

mark

给定x,μ和σ后,dnorm()这个函数返回的就是会返回上面的这个公式的值,这个值就是Z-score,如果是标准正态分布,那么上述的公式就变成了这个样子,如下所示:

mark

现在看一个案例,如下所示:

dnorm(0,mean=0,sd=1)
# 这个是标准正态分布函数
# [1] 0.3989423

dnorm(0,mean=0,sd=1)由于是标准正态分布函数的概率密度,这个命令其实可以直接写为dnorm(0)即可,如下所示:

dnorm(0)
# [1] 0.3989423

再看一个非标准正态分布的案例,如下所示:

dnorm(2, mean = 5, sd = 3)
# [1] 0.08065691

虽然在dnorm()中,x是一个概率密度函数(PDF,Probability Density Function)的独立变量,但它也能看作是一组经过Z转换后的一组变量,现在我们看一下使用dnorm来绘制一个正态分布的概率密度函数曲线,如下所示:

z_scores <>3,3,0.1)
# 生成一个Z-score的向量

z_scores
# [1] -3.0 -2.9 -2.8 -2.7 -2.6 -2.5 -2.4 -2.3 -2.2 -2.1 -2.0 -1.9 -1.8 -1.7 -1.6 -1.5
# [17] -1.4 -1.3 -1.2 -1.1 -1.0 -0.9 -0.8 -0.7 -0.6 -0.5 -0.4 -0.3 -0.2 -0.1  0.0  0.1
# [33]  0.2  0.3  0.4  0.5  0.6  0.7  0.8  0.9  1.0  1.1  1.2  1.3  1.4  1.5  1.6  1.7
# [49]  1.8  1.9  2.0  2.1  2.2  2.3  2.4  2.5  2.6  2.7  2.8  2.9  3.0

现在使用dnorm()函数计算一下Z_scores的概率密度,如下所示:

dvalues <>
dvalues
# [1] 0.004431848 0.005952532 0.007915452 0.010420935 0.013582969 0.017528300
# [7] 0.022394530 0.028327038 0.035474593 0.043983596 0.053990967 0.065615815
# [13] 0.078950158 0.094049077 0.110920835 0.129517596 0.149727466 0.171368592
# [19] 0.194186055 0.217852177 0.241970725 0.266085250 0.289691553 0.312253933
# [25] 0.333224603 0.352065327 0.368270140 0.381387815 0.391042694 0.396952547
# [31] 0.398942280 0.396952547 0.391042694 0.381387815 0.368270140 0.352065327
# [37] 0.333224603 0.312253933 0.289691553 0.266085250 0.241970725 0.217852177
# [43] 0.194186055 0.171368592 0.149727466 0.129517596 0.110920835 0.094049077
# [49] 0.078950158 0.065615815 0.053990967 0.043983596 0.035474593 0.028327038
# [55] 0.022394530 0.017528300 0.013582969 0.010420935 0.007915452 0.005952532
# [61] 0.004431848

现在绘图,如下所示:

plot(z_scores,dvalues, # Plot where y = values and x = index of the value in the vector
     type = 'l'# Make it a line plot
     main = 'pdf of the Standard Normal',
     xlab= 'Z-score'
mark

从上面的结果可以看出,在每个Z-score处,dnorm可以绘制出这个Z-score对应的正态分布的pdf的高度。

pnorm

pnorm函数中的p表示Probability,它的功能是,在正态分布的PDF曲线上,返回从负无穷到q的积分,其中这个q指的是一个Z-score。现在我们大概就可以猜测出pnorm(0)的值是0.5,因为在标准正态分布曲线上,当Z-score等于0时,这个点正好在标准正态分布曲线的正中间,那么从负无穷到0之间的曲线面积就是整个标准正态分布曲线下面积的一半,如下所示:

pnorm(0)
# pnorm()默认的参数与dnorm()一样,都是标准正态分布
# 即平均数为0,标准差为1的正态分布

# [1] 0.5

pnorm函数还能使用lower.tail参数,如果lower.tail设置为FALSE,那么pnorm()函数返回的积分就是从q到正无穷区间的PDF下的曲线面积,因此我们就知道了,pnorm(q)1-pnorm(q,lower.tail=FALSE)的结果是一样的,如下所示:

pnorm(2)
# [1] 0.9772499

pnorm(2, mean = 5, sd = 3)
# [1] 0.1586553

pnorm(2, mean = 5, sd = 3, lower.tail = FALSE)
# [1] 0.8413447

1 - pnorm(2, mean = 5, sd = 3, lower.tail = FALSE)
# [1] 0.1586553

在计算机出现之前的时代里,统计学家们使用正态分布进行统计时,通常是要查正态分布表的,但是,在计算机时代,通常都不使用正态分布表了,在R中,pnorm()这个函数完全可以取代正态分布表了,现在我们使用一个Z-scores的向量来计算一下相应的累积概率,如下所示:

# 此处还使用前面生成的z_scores
z_scores
# [1] -3.0 -2.9 -2.8 -2.7 -2.6 -2.5 -2.4 -2.3 -2.2 -2.1 -2.0 -1.9 -1.8 -1.7 -1.6 -1.5
# [17] -1.4 -1.3 -1.2 -1.1 -1.0 -0.9 -0.8 -0.7 -0.6 -0.5 -0.4 -0.3 -0.2 -0.1  0.0  0.1
# [33]  0.2  0.3  0.4  0.5  0.6  0.7  0.8  0.9  1.0  1.1  1.2  1.3  1.4  1.5  1.6  1.7
# [49]  1.8  1.9  2.0  2.1  2.2  2.3  2.4  2.5  2.6  2.7  2.8  2.9  3.0

pvalues <>
pvalues
# [1] 0.001349898 0.001865813 0.002555130 0.003466974 0.004661188 0.006209665
# [7] 0.008197536 0.010724110 0.013903448 0.017864421 0.022750132 0.028716560
# [13] 0.035930319 0.044565463 0.054799292 0.066807201 0.080756659 0.096800485
# [19] 0.115069670 0.135666061 0.158655254 0.184060125 0.211855399 0.241963652
# [25] 0.274253118 0.308537539 0.344578258 0.382088578 0.420740291 0.460172163
# [31] 0.500000000 0.539827837 0.579259709 0.617911422 0.655421742 0.691462461
# [37] 0.725746882 0.758036348 0.788144601 0.815939875 0.841344746 0.864333939
# [43] 0.884930330 0.903199515 0.919243341 0.933192799 0.945200708 0.955434537
# [49] 0.964069681 0.971283440 0.977249868 0.982135579 0.986096552 0.989275890
# [55] 0.991802464 0.993790335 0.995338812 0.996533026 0.997444870 0.998134187
# [61] 0.998650102

plot(pvalues, 
     xaxt = 'n'# 不绘制x轴的刻度
     type = 'l'# 使用曲线将各点连接起来
     main = '标准正态分布的CDF曲线',
     xlab= '分位数(Quantiles)',
     ylab='概率密度(Probability Density)'

# 以下是添加x轴的刻度
# These commands label the x-axis
axis(1, at=which(pvalues == pnorm(-2)), labels=round(pnorm(-2), 2))
axis(1, at=which(pvalues == pnorm(-1)), labels=round(pnorm(-1), 2))
axis(1, at=which(pvalues == pnorm(0)), labels=c(.5))
axis(1, at=which(pvalues == pnorm(1)), labels=round(pnorm(1), 2))
axis(1, at=which(pvalues == pnorm(2)), labels=round(pnorm(2), 2))
mark

以上就是标准正态分布的累积分布函数(CDF,Cumulative Distribution Function)曲线。

qnorm

简单来说,qnorm是正态分布累积分布函数(CDF,Cumulative Distribution Function)的反函数,也就是说它可以视为pnorm的反函数,这里的q指的是quantile,即分位数。

使用qnorm这个函数可以回答这个问题:正态分布中的第p个分位数的Z-score是多少?

现在我们来计算一下,在正态分布分布中,第50百分位数的Z-score是多少,如下所示:

qnorm(0.5)
# [1] 0
# 这里计算的就是在标准正态分布中,第50百分位数的Z-score是多少

pnorm(0)
# [1] 0.5
# 这里计算的就是在标准正态分布中,当Z-score是0时,它对应的曲线下面积是多少,也就是对应的是哪个百分位数

再来看一个案例:在正态分布中,第96个百分位的Z-score是多少,如下所示:

qnorm(.96)
# [1] 1.750686

再来看一个案例:在正态分布中,第99个百分位的Z-score是多少,如下所示:

qnorm(0.99)
# [1] 2.326348

再来看一下pnorm()这个函数,如下所示:

pnorm(qnorm(0))
# [1] 0

pnorm(2.326348)
# [1] 0.99

从上面我们可以看到,pnorm这个函数的功能是,我们知道某个Z-score是多少,它位于哪个分位数上。

接着我们进一步举例来说明一下qnormpnorm的具体功能,如下所示:

oldpar <>
par(mfrow=c(1,2))
# 设置绘图页面,页面布局是一行两列

quantiles <>01, by = .05)
# 以5%为步长,生成0到1的百分数
quantiles
# [1] 0.00 0.05 0.10 0.15 0.20 0.25 0.30 0.35 0.40 0.45 0.50 0.55 0.60 0.65 0.70 0.75
# [17] 0.80 0.85 0.90 0.95 1.00

qvalues <>
# 计算每个百分位数对应的Z-score
qvalues
# [1]       -Inf -1.6448536 -1.2815516 -1.0364334 -0.8416212 -0.6744898 -0.5244005
# [8] -0.3853205 -0.2533471 -0.1256613  0.0000000  0.1256613  0.2533471  0.3853205
# [15]  0.5244005  0.6744898  0.8416212  1.0364334  1.2815516  1.6448536        Inf

现在进行绘图,如下所示:

plot(qvalues,
     type = 'l'# We want a line graph
     xaxt = 'n'# No x-axis
     xlab='概率密度(Probability Density)',
     ylab='Z-scores')

# Same pnorm plot from before
plot(pvalues, # Plot where y = values and x = index of the value in the vector
     xaxt = 'n'# Don't label the x-axis
     type = 'l'# Make it a line plot
     main = '标准正态分布的CDF曲线',
     xlab= '分位数(Quantiles)',
     ylab='概率密度(Probability Density)'

# 绘制x轴的刻度
axis(1, at=which(pvalues == pnorm(-2)), labels=round(pnorm(-2), 2))
axis(1, at=which(pvalues == pnorm(-1)), labels=round(pnorm(-1), 2))
axis(1, at=which(pvalues == pnorm(0)), labels=c(.5))
axis(1, at=which(pvalues == pnorm(1)), labels=round(pnorm(1), 2))
axis(1, at=which(pvalues == pnorm(2)), labels=round(pnorm(2), 2))
mark

rnorm

rnomr()函数的功能用于生成一组符合正态分布的随机数,在学习各种统计学方法时,rnorm这个函数应该是最常用的,它的参数有n,meansd,其中n表示生成的随机数,mean与sd分别表示正态分布的均值与标准差,现在举个例子,如下所示:

set.seed(1000)
# 设定随身数种子

rnorm(5)
# 生成5个服从标准正态分布的随机数
# [1] -0.44577826 -1.20585657  0.04112631  0.63938841 -0.78655436

n10 <>10, mean = 70, sd = 5);n10
# 生成10个,服从均值为70,标准差为5的正态分布的随机数
# [1] 71.80351 60.47042 73.38245 74.64034 73.20814 75.98877 78.17864 68.84888 72.23209
# [10] 81.19844

n100 <>100, mean = 70, sd = 5);n100[1:10]
# 生成100个,服从均值为70,标准差为5的正态分布的随机数
# [1] 62.09470 72.75453 65.42062 68.65545 76.84043 74.17830 75.40543 65.32326 70.71987
# [10] 70.81957

n10000 <>10000, mean = 70, sd = 5);n10000[1:10]
# 生成1000个,服从均值为70,标准差为5的正态分布的随机数
# [1] 66.14695 70.16345 69.54554 76.15484 74.54789 71.78985 67.85345 73.85163 67.58083
# [10] 73.98425

现在我们绘制一下上面的几个向量的直方图,看一下它们的均值是否在70附近,如下所示:

oldpar <>
par(mfrow=c(1,3))

# breaks为设置直方图的宽度
hist(n10, breaks = 5)
hist(n100, breaks = 20)
hist(n10000, breaks = 100)
mark

在R语言中,生成不同分布的各种类型的函数都是以d,p,q,r开头的,使用原理跟上面的正态分布都一样。

参考资料

  1. Introduction to dnorm, pnorm, qnorm, and rnorm for new biostatisticians

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多