R повторять до тех пор, пока не будет выполнено условие

Я пытаюсь создать случайную выборку, которая исключает определенные "плохие данные". Я не знаю, являются ли данные "плохими" до тех пор, пока я не опробовать его. Таким образом, мне нужно сделать случайную ничью у населения, а затем проверить ее. Если данные "хорошие", то сохраните их. Если данные "плохие", тогда случайным образом нарисуйте другой и проверьте его. Я хотел бы сделать это, пока размер моего образца не достигнет 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)

Ответ 1

Вот общее использование цикла 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)
}

Альтернативой является использование repeat (синтаксический сахар для while(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 > 0) return(x) для выхода из функции напрямую.

Ответ 2

 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

Ответ 3

используйте это после первого образца

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

Ответ 4

Вы можете просто выбрать строки для выборки непосредственно так (всего 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.