R重复功能直到满足条件

Posted

技术标签:

【中文标题】R重复功能直到满足条件【英文标题】:R repeat function until condition met 【发布时间】: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”,除非示例中没有其他内容,它只是简化为一个简单的子集问题 【参考方案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) 直接退出该功能。

【讨论】:

以上是关于R重复功能直到满足条件的主要内容,如果未能解决你的问题,请参考以下文章

Python Selenium,被动等待,直到满足某些页面条件,然后接管[重复]

用重复数据填充数据框,直到满足特定条件

在循环内进行重复的ajax调用,直到满足条件

尝试循环 API 调用直到满足条件

迭代地和分层地循环遍历行,直到满足条件

循环