前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >103-R茶话会18-随机数和取子集是天生不和吗?

103-R茶话会18-随机数和取子集是天生不和吗?

作者头像
北野茶缸子
发布2022-04-05 15:16:00
3440
发布2022-04-05 15:16:00
举报

前言

昨天写的[[102-R数据整理12-缺失值的高级处理:用mice进行多重填补]],后台收到了一位朋友有意思的反馈。

经过my_data[sample(153, 10), ]$Wind <- NA 处理过后,整个数据框的结构发生了变化。

不难发现,第一张图中,有许多行的非缺失值部分变得一模一样了。这是为什么呢?是我的取子集操作出了问题吗?亦或是,sample 函数有什么魔法?

一起来探索一下吧。

sample 操作前后

代码语言:javascript
复制
my_data <- airquality
my_data2 <- my_data
my_data[sample(153, 10), ]$Wind <- NA

> which(my_data2$Ozone %in% NA)
 [1]   5  10  22  25  26  27  32  33  34  36  37  39
[13]  42  43  46  52  53  54  55  57  58  59  60  61
[25]  65  72  75  83  84 102 103 107 115 119 150
> which(my_data$Ozone %in% NA)
 [1]   5  10  22  25  26  27  32  33  34  36  37  39
[13]  42  43  45  46  52  53  54  55  57  58  59  60
[25]  61  65  72  75  83  84 102 103 107 115 119 150

很奇怪啊,我们对Wind 列做了NA 值处理,可是Ozone 列怎么反倒还少了一个缺失值呢?

再查看一下summary:

代码语言:javascript
复制
> summary(my_data)
     Ozone           Solar.R           Wind       
 Min.   :  1.00   Min.   :  7.0   Min.   : 1.700  
 1st Qu.: 18.00   1st Qu.:115.8   1st Qu.: 7.400  
 Median : 31.50   Median :205.0   Median : 9.700  
 Mean   : 42.13   Mean   :185.9   Mean   : 9.958  
 3rd Qu.: 63.25   3rd Qu.:258.8   3rd Qu.:11.500  
 Max.   :168.00   Max.   :334.0   Max.   :20.700  
 NA's   :37       NA's   :7                       
      Temp           Month            Day      
 Min.   :56.00   Min.   :5.000   Min.   : 1.0  
 1st Qu.:72.00   1st Qu.:6.000   1st Qu.: 8.0  
 Median :79.00   Median :7.000   Median :16.0  
 Mean   :77.88   Mean   :6.993   Mean   :15.8  
 3rd Qu.:85.00   3rd Qu.:8.000   3rd Qu.:23.0  
 Max.   :97.00   Max.   :9.000   Max.   :31.0
代码语言:javascript
复制
> summary(my_data2)  
 Ozone           Solar.R           Wind   
 Min.   :  1.00   Min.   :  7.0   Min.   : 1.700   
 1st Qu.: 18.00   1st Qu.:100.0   1st Qu.: 7.400   
 Median : 30.00   Median :194.0   Median : 9.700   
 Mean   : 41.51   Mean   :182.3   Mean   : 9.892   
 3rd Qu.: 63.25   3rd Qu.:259.0   3rd Qu.:11.500   
 Max.   :168.00   Max.   :334.0   Max.   :20.700   
 NA's   :36       NA's   :10      NA's   :10        
      Temp           Month            Day         
 Min.   :56.00   Min.   :5.000   Min.   : 1.00    
 1st Qu.:72.00   1st Qu.:6.000   1st Qu.: 8.00    
 Median :78.00   Median :7.000   Median :16.00    
 Mean   :77.36   Mean   :6.928   Mean   :15.88    
 3rd Qu.:84.00   3rd Qu.:8.000   3rd Qu.:23.00    
 Max.   :97.00   Max.   :9.000   Max.   :31.00    
 NA's   :10

可见不仅仅是Onze,就连Temp, Solar 也受到了迫害,这是怎么了?

用小样本继续测试

那么,会不会是我本身取子集的方式出了问题呢?对小样本的sample 与直接获得sample 指定种子结果,分别测试一下。

代码语言:javascript
复制
> my_data3 <- my_data[1:10,]

> set.seed(1)
> tmp = sample(10,5)
> tmp
[1] 9 4 7 1 2
> my_data5 <- my_data3
> my_data5[tmp,]$Wind <- NA

> set.seed(1)
> my_data4[sample(10,5),]$Wind <- NA

直接来看看数据框好了:

不难发现,下图并没有什么问题,对应的rownames 下的内容的Wind 套上了NA;但是,上图中的sample 还是如前所述般的诡异,好像其他行被施了魔法,全部大变样。

sample 改变数据框并不是随机的

虽然我们设定了种子set.seed(1),可最终出的结果确实离谱他奶奶给离谱开门,离谱到家了。

可如果是重复这个过程呢。

代码语言:javascript
复制
> set.seed(1)
> my_data3[sample(10,5),]
  Ozone Solar.R Wind Temp Month Day
9     8      19 20.1   61     5   9
4    18     313 11.5   62     5   4
7    23     299  8.6   65     5   7
1    41     190  7.4   67     5   1
2    36     118  8.0   72     5   2
> set.seed(1)
> my_data3[sample(10,5),]$Wind <- NA
> set.seed(1)
> my_data3[sample(10,5),]$Wind
[1] 20.1 11.5   NA   NA   NA

重复之后,亦是如此,使用rep 也并非赋值长度的问题:

代码语言:javascript
复制
> my_data4 <- my_data3
> set.seed(1)
> my_data4[sample(10,5),]$Wind <- rep(NA,5)
> my_data4[sample(10,5),]$Wind
[1] 20.1 11.5   NA   NA   NA

仿佛前两个内容被锁定住了似的,即使我们把NA 替换为5:

代码语言:javascript
复制
> my_data4[sample(10,5),]$Wind 
[1] 20.1 11.5  5.0  5.0  5.0

虽然sample 并没有听我们的话使用指定的下标赋值,但是,其执行确实存在一定的规律。

其他随机函数亦是如此

同样涉及到随机数的runif:

代码语言:javascript
复制
> set.seed(1)
> my_data4[round(runif(5,1,10)),]$Wind 
[1] 12.6 11.5 14.9 20.1 12.6
> set.seed(1)
> my_data4[round(runif(5,1,10)),]$Wind <- NA
> set.seed(1)
> my_data4[round(runif(5,1,10)),]$Wind
[1] 12.6 11.5 14.9   NA 12.6

所以这个结论可以从sample 推广到全部随机数函数吗?

尝试拆解赋值过程

如果并不赋值,直接取子集呢?

代码语言:javascript
复制
> my_data3[sample(10,5),]$Wind
[1] 20.1 11.5  8.6  7.4  8.0
> tmp
[1] 9 4 7 1 2
> set.seed(1)
> my_data3[tmp,]$Wind
[1] 20.1 11.5  8.6  7.4  8.0

而上述奇怪的结果,怀疑和取子集有关:

代码语言:javascript
复制
> my_data4[c(4,4,4),]
    Ozone Solar.R Wind Temp Month Day
4      18     313 11.5   62     5   4
4.1    18     313 11.5   62     5   4
4.2    18     313 11.5   62     5   4

可惜我没有证据。

恐怖的一幕:

代码语言:javascript
复制
> set.seed(1)
> my_data4[sample(10,5), ]$Wind
[1] 20.1 11.5   NA   NA   NA
> my_data4[sample(10,5), ]$Wind
[1] NA NA NA NA NA
> set.seed(1)
> sample(10,5)
[1] 9 4 7 1 2
> sample(10,5)
[1] 7 2 3 8 1

总结

至此我们可以判断,我们实际设定的种子set.seed(1),并没有第一步就被数据框进行取子集操作,其使用的实际是该种子的下一批种子。

现在可以解释为什么下标没有对应了。

也就是说,如果需要使用随机数对数据框进行取子集操作,最好还是先将随机结果赋值,防止这样的意外。

那么下一个问题,数据框为什么会被改变呢?这我就不知道了。

欢迎来后台找我讨论。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2022-02-23,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 北野茶缸子 微信公众号,前往查看

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

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

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
  • sample 操作前后
  • 用小样本继续测试
  • sample 改变数据框并不是随机的
  • 其他随机函数亦是如此
  • 尝试拆解赋值过程
  • 总结
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档