【问题标题】:How to generate random numbers in a data.frame with range如何在具有范围的data.frame中生成随机数
【发布时间】:2015-08-18 17:00:03
【问题描述】:

我有一个data.frame,我想按一个序列为每个列表生成随机数。

我使用sample 函数创建随机数,但即使我为列表[[1]] 创建了随机数,用于设置[[2]] 再次产生相同的数字。那么,在这里我如何为集合[[2]] 创建不同的随机数。

这里是简单的代码;

data.list <- lapply(1:2, function(x) {
nrep <- 1
time <- rep(seq(90,54000,by=90),times=nrep) 
Mx <- rep(sort(sample(seq(0.012,-0.014,length.out = 600),replace=TRUE)), times=nrep)
My <- rep(sort(sample(seq(0.02,-0.02,length.out = 600),replace=TRUE)), times=nrep)
Mz <- rep(sort(sample(seq(-1,1,length.out=600),replace=TRUE)), times=nrep)
data.frame(time,Mx,My,Mz,set_nbr=x)
})

这是提供每个数据集的前 5 行

[[1]]
      time       Mx            My           Mz       set_nbr
1      90 -1.391319e-02 -2.000000e-02 -1.000000000       1
2     180 -1.386978e-02 -1.986644e-02 -1.000000000       1
3     270 -1.386978e-02 -1.973289e-02 -0.996661102       1
4     360 -1.382638e-02 -1.973289e-02 -0.993322204       1
5     450 -1.382638e-02 -1.973289e-02 -0.979966611       1  
..     ..  ....            ....         ....           ...

[[2]]

      time       Mx            My           Mz       set_nbr
1      90 -1.395659e-02 -0.0200000000 -1.000000000       2
2     180 -1.391319e-02 -0.0199332220 -0.993322204       2
3     270 -1.386978e-02 -0.0199332220 -0.993322204       2
4     360 -1.386978e-02 -0.0199332220 -0.993322204       2
5     450 -1.382638e-02 -0.0199332220 -0.986644407       2
..     ..  ....            ....         ....           ...

编辑 1:

关于@bgoldst 的回答,我现在可以产生不同的数字

set.seed(1);
data.list <- lapply(1:2, function(x) {
nrep <- 1;
time <- rep(seq(90,54000,by=90),times=nrep);
Mx <- rep(sort(runif(600,-0.014,0.012)),times=nrep);
My <- rep(sort(runif(600,-0.02,0.02)),times=nrep);
Mz <- rep(sort(runif(600,-1,1)),times=nrep);
data.frame(time,Mx,My,Mz,set_nbr=x);
});

另一方面,当我更改 nrep &lt;- 3; 时,会为每个 nrep 创建相同的数字。这是我想从一开始就避免的事情。

编辑 2:

@bgoldst 表明 replicate 完成了这项工作!

【问题讨论】:

  • 您不需要指定要sample 选择多少个号码吗?我认为您只是在此处保留整个 seq 向量。
  • @Vincent 也许这也可以。但我不知道如何设置:(
  • 我仔细查看了您的代码,每个数据集中产生的数字都不同...您能提供每个数据集的前 5 行吗?
  • 可以看到有些数字又被复制了。这不是我想要的。我想为MxMyMz 提供完全不同的数字(非常小的差异是可以的)。

标签: r random dataframe seq


【解决方案1】:

我认为您可能对sample() 的工作原理有些困惑。

首先,让我们检查sample() 相对于这个简单向量的行为:

1:5;
## [1] 1 2 3 4 5

当您将多元素向量传递给sample() 时,它基本上只是随机化了顺序。这意味着您每次都会得到不同的结果,或者更准确地说,向量越长,两次获得相同结果的可能性就越小:

set.seed(1); sample(1:5); sample(1:5); sample(1:5);
## [1] 2 5 4 3 1
## [1] 5 4 2 3 1
## [1] 2 1 3 4 5

这意味着如果您在采样后立即对其进行排序,那么您每次都会得到相同的结果。如果原始向量本身已排序,则结果也将等于该原始向量。不管sample()如何随机化顺序,这都是真的,因为顺序总是由sort()恢复:

set.seed(1); sort(sample(1:5)); sort(sample(1:5)); sort(sample(1:5));
## [1] 1 2 3 4 5
## [1] 1 2 3 4 5
## [1] 1 2 3 4 5

现在,如果您添加 replace=T(或者只是 rep=T,如果您想利用部分匹配进行简洁,我会这样做),那么您只是随机化顺序,您正在选择带有替换的size 元素,如果您没有明确提供size,则size 是向量长度。这意味着您可以在结果中获得重复的元素:

set.seed(1); sample(1:5,rep=T); sample(1:5,rep=T); sample(1:5,rep=T);
## [1] 2 2 3 5 2
## [1] 5 5 4 4 1
## [1] 2 1 4 2 4

所以,如果你对结果进行排序,你(很可能)不会返回原始向量,因为有些元素会被重复,有些元素会被省略:

set.seed(1); sort(sample(1:5,rep=T)); sort(sample(1:5,rep=T)); sort(sample(1:5,rep=T));
## [1] 2 2 2 3 5
## [1] 1 4 4 5 5
## [1] 1 2 2 4 4

这正是您的代码所发生的事情。您的输出向量 在两个列表组件之间是不同的,因为您在排序之前使用替换抽样,这意味着每个列表组件将发生不同的元素重复和省略。但是,由于您是从同一序列中采样并对结果进行排序,因此您必然会为每个列表组件获得外观相似的结果,即使它们并不相同。

我认为您可能正在寻找的是随机偏离均匀分布。你可以从runif()获得这些:

set.seed(1); runif(5,-0.014,0.012);
## [1] -0.0070967748 -0.0043247786  0.0008941874  0.0096134025 -0.0087562698
set.seed(1); runif(5,-0.02,0.02);
## [1] -0.009379653 -0.005115044  0.002914135  0.016328312 -0.011932723
set.seed(1); runif(5,-1,1);
## [1] -0.4689827 -0.2557522  0.1457067  0.8164156 -0.5966361

因此,您的代码将变为:

set.seed(1);
data.list <- lapply(1:2, function(x) {
    nrep <- 1;
    time <- rep(seq(90,54000,by=90),times=nrep);
    Mx <- rep(sort(runif(600,-0.014,0.012)),times=nrep);
    My <- rep(sort(runif(600,-0.02,0.02)),times=nrep);
    Mz <- rep(sort(runif(600,-1,1)),times=nrep);
    data.frame(time,Mx,My,Mz,set_nbr=x);
});

这给出了:

lapply(data.list,head);
## [[1]]
##   time          Mx          My         Mz set_nbr
## 1   90 -0.01395224 -0.01994741 -0.9967155       1
## 2  180 -0.01394975 -0.01991923 -0.9933909       1
## 3  270 -0.01378866 -0.01980934 -0.9905714       1
## 4  360 -0.01371306 -0.01977090 -0.9854065       1
## 5  450 -0.01371011 -0.01961713 -0.9850108       1
## 6  540 -0.01365998 -0.01960718 -0.9846628       1
##
## [[2]]
##   time          Mx          My         Mz set_nbr
## 1   90 -0.01398426 -0.01997718 -0.9970438       2
## 2  180 -0.01398293 -0.01989651 -0.9931286       2
## 3  270 -0.01397330 -0.01988715 -0.9923425       2
## 4  360 -0.01396455 -0.01957807 -0.9913645       2
## 5  450 -0.01384501 -0.01939597 -0.9892001       2
## 6  540 -0.01382531 -0.01931913 -0.9889356       2

编辑:从您的问题看来,您希望随机数在列表组件之间是不同的,也就是说,在从 1 生成的组件之间: 2 作为第一个参数传递给lapply()。每个随机向量 nrep 的重复次数 within 每个列表组件似乎不相关,部分原因是您将 nrep 设置为 1,因此没有任何实际重复。 p>

不过没关系,我们可以通过使用replicate() 而不是rep() 来实现这个要求,因为replicate() 实际上每次重复运行一次它的表达式参数。我们还必须将结果展平,因为replicate() 默认返回一个矩阵,而我们想要一个直向量:

set.seed(1);
data.list <- lapply(1:2, function(x) {
    nrep <- 2;
    time <- rep(seq(90,54000,by=90),times=nrep);
    Mx <- c(replicate(nrep,sort(runif(600,-0.014,0.012))));
    My <- c(replicate(nrep,sort(runif(600,-0.02,0.02))));
    Mz <- c(replicate(nrep,sort(runif(600,-1,1))));
    data.frame(time,Mx,My,Mz,set_nbr=x);
});
lapply(data.list,function(x) x[c(1:6,601:606),]);
## [[1]]
##     time          Mx          My         Mz set_nbr
## 1     90 -0.01395224 -0.01993431 -0.9988590       1
## 2    180 -0.01394975 -0.01986782 -0.9948254       1
## 3    270 -0.01378866 -0.01981143 -0.9943576       1
## 4    360 -0.01371306 -0.01970813 -0.9789037       1
## 5    450 -0.01371011 -0.01970022 -0.9697986       1
## 6    540 -0.01365998 -0.01969326 -0.9659567       1
## 601   90 -0.01396582 -0.01997579 -0.9970438       1
## 602  180 -0.01394750 -0.01997375 -0.9931286       1
## 603  270 -0.01387607 -0.01995893 -0.9923425       1
## 604  360 -0.01385108 -0.01994546 -0.9913645       1
## 605  450 -0.01375113 -0.01976155 -0.9892001       1
## 606  540 -0.01374467 -0.01973125 -0.9889356       1
##
## [[2]]
##     time          Mx          My         Mz set_nbr
## 1     90 -0.01396979 -0.01999198 -0.9960861       2
## 2    180 -0.01390373 -0.01995219 -0.9945237       2
## 3    270 -0.01390252 -0.01991559 -0.9925640       2
## 4    360 -0.01388905 -0.01978123 -0.9890171       2
## 5    450 -0.01386718 -0.01967644 -0.9835435       2
## 6    540 -0.01384351 -0.01958008 -0.9822988       2
## 601   90 -0.01396739 -0.01989328 -0.9971255       2
## 602  180 -0.01396433 -0.01985785 -0.9954987       2
## 603  270 -0.01390700 -0.01984074 -0.9903196       2
## 604  360 -0.01376890 -0.01982715 -0.9902251       2
## 605  450 -0.01366110 -0.01979802 -0.9829480       2
## 606  540 -0.01364868 -0.01977278 -0.9812671       2

【讨论】:

  • 非常感谢您非常清晰的解释。你提供给我的信息很有启发性。我将使用runif
  • 我开始意识到,如果我将 nrep 更改为 2 或 3、4、5,您会看到所有值一次又一次地重复,我关于这个问题的观点是如何在每次重复?
  • 谢谢,我有一个问题是关于如何成为像你一样的 R 专家,我的意思是当你看到问题时,你是如何快速理解并解决它的?我应该使用 R 书籍还是网络视频?我每天都在努力学习一小部分,但似乎还不够:(
  • @aoronbarlow R 是我学过的最难的语言之一。对我来说,可能只有 C++ 更难,然后只有 C++ 中更高级的模板。我想说这都是关于经验、经验、经验和努力识别语言中的模式,比如rep() vs. replicate(),和ave() vs. aggregate() vs. by(),还有apply 系列中有 8 个函数(实际上还有其他几个函数......),以及类似的东西。您拥有的经验越多,就能越快速有效地解决问题。
  • 是的,尽可能多地阅读书籍、网络视频和在线教程,直到您开始觉得自己了解所看到的所有信息。这是获得语言经验的最佳方式。
猜你喜欢
  • 2019-08-06
  • 2023-03-04
  • 2013-12-14
  • 2015-10-28
  • 1970-01-01
  • 2017-06-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多