【问题标题】:R repeat function until condition metR重复功能直到满足条件
【发布时间】:2013-12-28 17:22:48
【问题描述】:

我正在尝试生成排除某些“不良数据”的随机样本。我不知道数据是否“坏”,直到我采样之后。因此,我需要从人群中随机抽取,然后进行测试。如果数据“好”,则保留它。如果数据“不好”,则随机抽取另一个数据并进行测试。我想这样做,直到我的样本量达到 25。下面是我尝试编写一个执行此操作的函数的简化示例。谁能告诉我我错过了什么?

df <- data.frame(NAME=c(rep('Frank',10),rep('Mary',10)), SCORE=rnorm(20))
df

random.sample <- function(x) {
  x <- df[sample(nrow(df), 1), ]
  if (x$SCORE > 0) return(x)
 #if (x$SCORE <= 0) run the function again
}

random.sample(df)

【问题讨论】:

  • 你熟悉?while吗?
  • 我查看了 ?'while' 和 ?Control 但无法理解如何使用它。
  • 那么,画完还要计算吗?在这里,您已经有了 SCORE,只需将那些好的和样本子集即可。
  • @Ananta 那仍然是来自原始人群的随机样本吗?
  • @aseidlitz 它使用上面提到的相同信息“SCORE”,除非示例中没有其他内容,它只是简化为一个简单的子集问题

标签: r function conditional-statements repeat


【解决方案1】:
 random.sample <- function(x) {
   x <- df[sample(nrow(df), 1), ]
   if (x$SCORE > 0) return(x)
   Recall(x)# run the function again
 }

 random.sample(df)
#   NAME    SCORE
#14 Mary 1.252566

在我看来,这也应该有效:

 df$SCORE[ df$SCORE > 0 ][ sample(1:sum(df$SCORE > 0), 1) ]
#[1] 0.6579631

【讨论】:

  • 非常好的帮助。在我所有的 R 手册中甚至都没有提到 Recall 函数。如果我使用: if (x$SCORE > 0) { return(x) } else { Recall(x) } 会更好吗?
  • 优雅但不如 while 循环恕我直言,因为它可以创建一个大的调用堆栈。
  • 您实际上是在进行拒绝抽样。可以很简单:df$SCORE[df$SCORE &gt; 0][ sample(1:(sum(df$SCORE &gt; 0, 1)]。我不确定如何在复选标记上提供建议。我的答案基本上是一次性的。弗洛德尔关于效率是正确的。 R 中不支持递归。
  • 关于您的df$SCORE[df$SCORE &gt; 0][...],这与我对斯蒂芬的评论相同:OP 给出了一个更复杂情况的“简化示例”,其中“I直到我采样后才知道数据是否“坏””。因此,递归或 while 循环是唯一可能的解决方案。
【解决方案2】:

您可以像这样直接选择要采样的行(只有 5 行):

> df <- data.frame(NAME=c(rep('Frank',10),rep('Mary',10)), SCORE=rnorm(20))
> df[sample(which(df$SCORE>0), 5),]


 NAME     SCORE
14  Mary 1.0858854
10 Frank 0.7037989
16  Mary 0.7688913
5  Frank 0.2067499
17  Mary 0.4391216

这是没有替换的,用于引导放入replace=T

【讨论】:

  • 我投了赞成票,但由于 OP 说 我不知道数据是否“坏”,直到我对它进行采样我不确定它是否对他有用。他的榜样可能选择不当。
  • @flodel 很公平,但 R 不是实时应用程序,也不擅长递归函数调用,因此如果需要检查数据,则测试在数据中,应该向量化并放在括号之间。像这样。
  • 我是否保留观察是观察本身的函数。我无法确定是否要保留观察结果,直到绘制完成。
  • @user1491868 如果 obs 真的在一个 DF 中,那么你可以做到这一点,根据你的标准子集然后采样......无论如何它并不那么重要:)
  • 经过深思熟虑后,我决定在采样前按标准对数据进行子集化。但我仍然认为,当无法在采样之前对数据进行子集化时,这个线程很有用。感谢大家非常有帮助的 cmets 和建议。
【解决方案3】:

在你的第一个样本之后使用它

while (any(bad <- (x$SCORE <= 0)))
   x[bad, ] <- df[sample(nrow(df), sum(bad)), ]

【讨论】:

    【解决方案4】:

    这是while循环的一般用法:

    random.sample <- function(x) {
      success <- FALSE
      while (!success) {
        # do something
        i <- sample(nrow(df), 1)
        x <- df[sample(nrow(df), 1), ]
        # check for success
        success <- x$SCORE > 0
      }
      return(x)
    }
    

    另一种方法是使用repeatwhile(TRUE) 的语法糖)和break

    random.sample <- function(x) {
      repeat {
        # do something
        i <- sample(nrow(df), 1)
        x <- df[sample(nrow(df), 1), ]
        # exit if the condition is met
        if (x$SCORE > 0) break
      }
      return(x)
    }
    

    break 让你退出repeat 块。或者,您可以让if (x$SCORE &gt; 0) return(x) 直接退出该功能。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-11-09
      • 2015-07-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-05-12
      • 2019-11-10
      • 2014-05-03
      相关资源
      最近更新 更多