Подтвердить что ты не робот

Образец из вектора различной длины (в том числе 1)

У меня есть вектор с переменной длиной, который иногда может иметь длину 1.

Я хотел бы сделать выборку из этого вектора так, чтобы, если его длина была 1, он всегда выбирал это 1 число.

sample() не будет этого делать, потому что он производит выборку от 1 до цифры, когда размер выборки равен 1.

4b9b3361

Ответ 1

Это документированная функция:

Если x имеет длину 1, это numeric (в смысле is.numeric) и x >= 1, выборка через образец происходит из 1:x. Обратите внимание, что эта функция удобства может привести к нежелательному поведению, когда x имеет разную длину в вызовах, таких как sample(x).

Альтернативой является написать свою собственную функцию, чтобы избежать этой функции:

sample.vec <- function(x, ...) x[sample(length(x), ...)]
sample.vec(10)
# [1] 10
sample.vec(10, 3, replace = TRUE)
# [1] 10 10 10

Некоторые функции с аналогичным поведением перечислены в разделе seq vs seq_along. Когда использование seq приведет к непредвиденным результатам?

Ответ 2

При подаче только одного номера sample работает как sample.int (см. ?sample). Если вы хотите убедиться, что это только образцы из вектора, который вы ему даете, вы можете работать с индексами и использовать эту конструкцию:

x[sample(length(x))]

Это дает правильный результат независимо от длины x и без необходимости добавлять if -condition, проверяя длину.

Пример:

mylist <- list(
  a = 5,
  b = c(2,4),
  d = integer(0)
)

mysample <- lapply(mylist,function(x) x[sample(length(x))])

> mysample
$a
[1] 5

$b
[1] 2 4

$d
integer(0)

Примечание: вы можете заменить sample на sample.int, чтобы получить небольшое увеличение скорости.

Ответ 3

Вы можете использовать это "безошибочное" переопределение функции:

sample = function(x, size, replace = F, prob = NULL) {
  if (length(x) == 1) return(x)
  base::sample(x, size = size, replace = replace, prob = prob)
}

Проверьте это:

> sapply(1:7, base::sample, size = 1)
[1] 1 2 2 4 4 4 4
> sapply(1:7, sample)
[1] 1 2 3 4 5 6 7