Образец из вектора различной длины (в том числе 1)
У меня есть вектор с переменной длиной, который иногда может иметь длину 1.
Я хотел бы сделать выборку из этого вектора так, чтобы, если его длина была 1, он всегда выбирал это 1 число.
sample()
не будет этого делать, потому что он производит выборку от 1 до цифры, когда размер выборки равен 1.
Ответы
Ответ 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