前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >竟然被awk生成的随机数给整蒙了,也谈随机数生成种子

竟然被awk生成的随机数给整蒙了,也谈随机数生成种子

作者头像
生信宝典
发布2022-03-25 09:20:23
6100
发布2022-03-25 09:20:23
举报
文章被收录于专栏:生信宝典生信宝典

我们现在主要的一个业务是给科研单位等提供数据库构建服务,目前承接的数据库已经发表了3NAR文章,具体见你的数据也可以-三篇NAR的数据库

这次一位老师需要做数据库,但数据还没做好,时间要求却比较急,我们只能随机生成一些数据来作为测试先把数据库搭起来,等完成后再替换为真实数据,稍加测试,也就完成了。

最开始是这么生成随机数字的,看上去没问题,每运行一次都会生成一个随机数,符合预期。

代码语言:javascript
复制
awk 'BEGIN{OFS=FS="\t";}{ $2=100 * rand(); print $0;}' 00232503-7e34-479a-b6fb-0b52e78b554e.txt | cut -f 1-3 | head
Rnu7-186P    99.4034    ACC-3
Rnu2-41P    24.6362    ACC-3
代码语言:javascript
复制
awk 'BEGIN{OFS=FS="\t";}{ $2=100 * rand(); print $0;}' 00232503-7e34-479a-b6fb-0b52e78b554e.txt | cut -f 1-3 | head
Rnu7-186P    24.3382    ACC-3
Rnu2-41P    87.6752    ACC-3

但当放到一个for循环中时 ,问题就出来了,每次循环的随机数都一样:

代码语言:javascript
复制
for i in *.txt; do awk 'BEGIN{OFS=FS="\t";}{ $2=100 * rand(); print $0;}' $i | cut -f 1-3 | head -n 2; echo "------------"; done
Rnu7-186P    99.0514    ACC-3
Rnu2-41P    82.4637    ACC-3
------------
Rnu7-186P    99.0514    ACC-3
Rnu2-41P    82.4637    ACC-3
------------
Rnu7-186P    99.0514    ACC-3
Rnu2-41P    82.4637    ACC-3
------------

这猜测是每次循环时随机数发生器给的种子都是一致的,导致随机数在每个循环都一致了,修改如下:每次循环单独给一个随机数的种子就好了。

代码语言:javascript
复制
for i in `seq 1 3`; do awk -v seed=$RANDOM 'BEGIN{OFS=FS="\t";srand(seed);}{ $2=100 * rand(); print $0;}' 00232503-7e34-479a-b6fb-0b52e78b554e.txt | cut -f 1-3 | head -n 2; echo "------------"; done
Rnu7-186P    38.0502    ACC-3
Rnu2-41P    76.7106    ACC-3
------------
Rnu7-186P    99.1498    ACC-3
Rnu2-41P    65.7196    ACC-3
------------
Rnu7-186P    92.9258    ACC-3
Rnu2-41P    24.0214    ACC-3
------------

这就是awk自己的坑了。

In most awk implementations, including gawk, rand() starts generating numbers from the same starting number, or seed, each time you run awk. Thus, a program generates the same results each time you run it. The numbers are random within one awk run but predictable from run to run. This is convenient for debugging, but if you want a program to do different things each time it is used, you must change the seed to a value that is different in each run. To do this, use srand().

随机数生成器的种子

除了在显示生成随机数做测试时会用到随机数生成器,很多其它时候比如做Kmeans聚类时WGCNA分析时, 随机森林分析时也都会有随机过程,每次运行结果都有可能不同,为了保证结果的可重复性,这时就可以设置一个随机数种子。其原则是:种子定了,每次运行结果也就不会变了

通常这个种子是一个整数,任意整数都可以。讲课时,我一般说大家可以选择自己的幸运数字来设置,在R中通常通过函数set.seed来设置:

通常,如果我们没有自己设置种子,大部分程序语言中会调用当前的时间戳作为随机数的种子,每次操作时间都不同,时间戳也就不同,获得的随机数序列也就不同。

下面是一个R中的示例,可以看到前面两次运行rnorm(5)获得的返回值都不同。而在设置set.seed(10)后,两次运行rnorm(5)获得的返回值完全一致。当然这个设置只是对最近的命令有效,下面再运行一次rnorm(5),又是基于时间戳生成的完全不同的数据。

代码语言:javascript
复制
# 不设置
rnorm(5)
# [1]  1.1017795  0.7557815 -0.2382336  0.9874447  0.7413901
rnorm(5)
# [1]  0.08934727 -0.95494386 -0.19515038  0.92552126  0.48297852


set.seed(10)
rnorm(5)
# [1]  0.01874617 -0.18425254 -1.37133055 -0.59916772  0.29454513

set.seed(10)
rnorm(5)
# [1]  0.01874617 -0.18425254 -1.37133055 -0.59916772  0.29454513

rnorm(5)
[1]  0.3897943 -1.2080762 -0.3636760 -1.6266727 -0.2564784

关于随机数种子,虽然看上去比较简单,但每次课程,总会有多位老师问起,问起最多的就是为什么你选择10作为随机数种子?依据是什么?我怎么选?实际就记住两点:

  1. 同一个随机数种子获得的随机数序列是一致的,不管这个种子是10, 20还是 30
  2. 随机数种子可以是任意值,看心情选择就好,课程中选哪个也都是随机的。
本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2022-01-19,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 生信宝典 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 随机数生成器的种子
相关产品与服务
数据库
云数据库为企业提供了完善的关系型数据库、非关系型数据库、分析型数据库和数据库生态工具。您可以通过产品选择和组合搭建,轻松实现高可靠、高可用性、高性能等数据库需求。云数据库服务也可大幅减少您的运维工作量,更专注于业务发展,让企业一站式享受数据上云及分布式架构的技术红利!
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档