【问题标题】:Split vector randomly into two sets将向量随机分成两组
【发布时间】:2012-08-28 23:27:01
【问题描述】:

我有一个长度为 100 的向量 t,想将它分成 30 和 70 个值,但这些值应该是随机选择的,不能替换。所以这30个值都不允许在70个值的子向量中,反之亦然。

我知道 R 函数 sample,我可以使用它从向量中随机选择有无替换的值。但是,即使我使用 replace = FALSE,我也必须运行 sample 函数两次,一次选择 30,一次选择 70 个值。这意味着 30 个值中的一些值可能在 70 个值中,反之亦然。

有什么想法吗?

【问题讨论】:

  • 我很困惑。为什么不能使用sample() 随机选择 30 个,然后选择除 30 个随机样本之外的所有 other 作为另一组。根据定义,这两个集合是唯一的。
  • @GavinSimpson,这几乎就是我在回答中所做的,只是添加了一个分组变量来分割;但是,我仍然不确定他们到底在寻找什么。
  • 感谢您的所有回答!我尝试了不同的解决方案,它们似乎都有效。我刚刚遇到了一个不同的 R 包:ftp.ee.freebsd.org/pub/pkgsrc/current/pkgsrc/math/R-e1071/…,它实际上是我想要的。但是,我根本没有安装它。我下载了 .tgz 文件并尝试安装它,但它失败了......
  • 你在运行 FreeBSD 吗?如果不是,你为什么要安装它的 tarball 之一?使用你的 R 风格提供的任何工具来安装包,但如果你有互联网,启动 R 并执行 install.packages("e1071"), depend = TRUE) 来安装包,然后 library("e1071") 加载它以准备在当前会话中使用。
  • 您能否也回复 cmets 要求澄清您想要实现的目标?如果t 具有非唯一值,则会出现一些混乱,并且大多数答案都会失败。

标签: r random sample random-sample


【解决方案1】:

关于我的评论,有什么问题:

vec <- 1:100
set.seed(2)
samp <- sample(length(vec), 30)

a <- vec[samp]
b <- vec[-samp]

?

为了显示这些是没有重复的独立集合:

R> intersect(a, b)
integer(0)

如果你的向量中有重复的值,那是另一回事,但你的问题不清楚。

vec 中的重复项会稍微复杂一些,这取决于您想要达到的结果。

R> set.seed(4)
R> vec <- sample(100, 100, replace = TRUE)
R> set.seed(6)
R> samp <- sample(100, 30)
R> a <- vec[samp]
R> b <- vec[-samp]
R> length(a)
[1] 30
R> length(b)
[1] 70
R> length(setdiff(vec, a))
[1] 41

所以setdiff()“失败”在这里,因为它没有得到正确的长度,但随后ab 包含重复值(但不是观察!来自样本):

R> intersect(a, b)
 [1] 57 35 91 27 71 63  8 92 49 77

出现重复(交集)是因为上述值在原始样本vec中出现了两次@

【讨论】:

    【解决方案2】:

    这样的事情呢?

    x <- 1:100
    s70 <- sample(x, 70, replace=FALSE)
    s30 <-sample(setdiff(x, s70), 30, replace=FALSE)
    

    s30 将与setdiff(x, s70) 具有相同的数字,它们之间的区别是: s30 长度为 30 的无序向量和 setdiff(x, s70) 将为您提供长度为 30 的(升序)有序向量。您说您想要长度为 70 和 30 的随机子样本,因此 s30setdiff(x, s70) 更好。如果顺序并不重要,那么更好的选择是使用setdiff 而不使用@seancarmody 的答案中的sample

    【讨论】:

    • 快!虽然你并不真的需要第二个例子中的样本,除非你想打乱顺序,这在 OP 中并不是很清楚(“分为 30 和 70 值......”)
    【解决方案3】:

    正如你提到的“分裂”,你也可以尝试这样的事情:

    set.seed(1)
    t <- sample(20:40, 100, replace=TRUE)
    groups <- rep("A", 100)
    groups[sample(100, 30)] <- "B"
    table(groups)
    # groups
    #  A  B 
    # 70 30
    split(t, groups)
    # $A
    #  [1] 25 32 39 24 38 39 33 21 24 23 36 40 27 36 24 33 22 25 28 28 38 27 30 30 23
    # [26] 34 35 37 33 31 36 20 30 35 34 30 29 25 22 26 33 28 26 29 26 33 30 36 21 38
    # [51] 27 37 27 27 30 38 38 36 29 34 28 26 35 25 23 25 21 33 36 28
    # 
    # $B
    #  [1] 27 33 34 28 30 35 39 20 32 37 36 22 28 36 31 38 21 30 39 25 28 40 24 34 22
    # [26] 38 36 29 37 32
    

    【讨论】:

    • 我认为 OP 想要没有替换的样本,并且第一个向量中的那些值不能包含在第二个向量中。不是吗?
    • @Jilber,我认为这个问题并不完全清楚。如果我使用我的“t”和你的答案或肖恩的答案,第一步很好,但第二步不起作用。您是否尝试过使用比 1:100 更整洁的数据来回答?我的假设是他们关心的是根据索引或位置而不是值来选择数字。
    • 根据您的假设,您是对的。是的,这个问题还不够清楚。
    【解决方案4】:

    这个怎么样:

    t <- 1:100 # or whatever your original set is
    a <- sample(t, 70)
    b <- setdiff(t, a)
    

    【讨论】:

    • 与其他一些条目的评论相同; setdiff() 方法仅在 isTRUE(all(!duplicated(t))) 时有效。如果有重复的值,它就会“失败”。
    • 同意,但我怀疑 OP 有一个具有唯一值的向量(否则,避免替换采样似乎不太重要)。
    • 在这种情况下,一旦你有了第一个样本(比如 30 个),你可以通过负索引来获取其他样本,你不需要setdiff()。这个工作有点过头了吧?
    • t1:100 但上述方法适用于任何向量t 的唯一条目。当然,另一种选择是坚持抽样1:100 并使用负索引,但让样本代表索引而不是样本,就像你所做的那样。
    猜你喜欢
    • 1970-01-01
    • 2013-05-18
    • 2015-09-18
    • 1970-01-01
    • 2021-10-30
    • 2021-04-11
    • 1970-01-01
    • 2014-05-10
    • 1970-01-01
    相关资源
    最近更新 更多