15.2 随机数
随机数对许多分析都至关重要,R具有多种从不同分布中采样的函数。
15.2.1 示例函数
我们已多次看到sample
函数(它首次出现在第3章)。这是一个用于生成随机数的重要的核心函数,而其行为有些怪诞,因而我们要对它做更深入的了解。如果你仅传递一个数值n
给它,它将返回从一个1到n
的自然数的排列:
sample(7)
## [1] 1 2 5 7 4 6 3
如果你给它传递第二个参数m
,它将返回m
个1和n
之间的随机数:
sample(7, 5)
## [1] 7 2 3 1 5
请注意,所有这些随机数都是不同的。默认情况下,sample
函数不会重复样本。也就是说,每个值只能出现一次。如果要允许有重复抽样,可传递replace = TRUE
参数:
sample(7, 10, replace = TRUE)
## [1] 4 6 1 7 5 3 6 7 4 2
当然,大多数情况下,返回自然数并不有趣,但sample
足够灵活,它可以让我们从任何喜欢的向量中采样。最常见的是给它传递一个字符向量:
sample(colors(), 5) # 为你家房子选择颜色的好方法
## [1] "grey53" "deepskyblue2" "gray94" "maroon2"
## [5] "gray18"
如果我们再冒些险,可以传递日期给它:
sample(.leap.seconds, 4)
## [1] "2012-07-01 01:00:00 BST" "1994-07-01 01:00:00 BST"
## [3] "1981-07-01 01:00:00 BST" "1990-01-01 00:00:00 GMT"
还可以通过传递prob
参数来定义每个输入值的概率权重。在下例中,我们使用R来随机地决定哪个月去度假,然后改变数据以增加我们放暑假的机会:
weights <- c(1, 1, 2, 3, 5, 8, 13, 21, 8, 3, 1, 1)
sample(month.abb, 1, prob = weights)
## [1] "Jul"
15.2.2 从分布中抽样
通常情况下,我们想根据某种概率分布来生成随机数。R的各种包中一共提供了近百个分布函数、mixture和系动词用于抽样。?Distribution
帮助页面文件记录了R基本包里的函数。如果你还想了解更多秘决,CRAN Task View: Probability Distributions(http://cran.r-project.org/web/views/Distributions.html)提供了更多的选择。
大部分的随机数生成函数的名称都是r
。例如,我们已经看到的runif
,它能生成均匀分布的随机数,还有rnorm
能生成正态分布的随机数。这些函数的第一个参数都是要生成的随机数的数量,其太参数则会影响分布的形状。例如,runif
允许你设置分布的上限和下限:
runif(5) #生成5个介于0和1之间的均匀分布的随机数
runif(5, 1,10) #生成5个介于0和10之间的均匀分布的随机数
rnorm(5) #生成5个正态分布的随机数,它们的中位数为0,标准差为1
rnorm(5, 3, 7) #生成5个正态分布的随机数,它们的中位数为3,标准差为7
与任何其他软件一样,由R生成的随机数字实际上都是伪随机的。也就是说,它们是由某种算法而不是由真正的随机过程产生的。R支持多种优质算法,就像?RNG
页面中所描述的一样。还有一些更专业的算法(如并行数生成)位于其他包中。以上提及的CRAN Task View on distributions也指出在哪里能找到更多这样的算法。你可以看到使用RNGKind
函数以及哪些算法用于均匀和正态随机数的生成(从其他分布中采样通常也使用相同的均匀和正态随机数函数):
RNGkind()
## [1] "Mersenne-Twister" "Inversion"
随机数发生器需要一个初始值来生成数字,此初始值即所谓的“种子”。通过把种子设置为特定的值,可保证每次运行同一段代码时能生成相同的随机数。例如,本书可以使用固定的种子值,使本书创建的范例在每次运行时都相同。使用set.seed
函数设置种子值。它的输入参数为一个正整数。你选择哪个整数都无所谓,不同的种子将给出不同的随机数:
set.seed(1)
runif(5)
## [1] 0.2655 0.3721 0.5729 0.9082 0.2017
set.seed(1)
runif(5)
## [1] 0.2655 0.3721 0.5729 0.9082 0.2017
set.seed(1)
runif(5)
## [1] 0.2655 0.3721 0.5729 0.9082 0.2017
你也可以指定不同的生成算法,这种用法相当高级,不要贸然采用此做法除非很有把握。