#r #floating-point
#r #пример
Вопрос:
Мы знаем, что prob
аргумент in sample
используется для присвоения вероятности весов.
Например,
table(sample(1:4, 1e6, replace = TRUE, prob = c(0.2, 0.4, 0.3, 0.1)))/1e6
# 1 2 3 4
#0.2 0.4 0.3 0.1
table(sample(1:4, 1e6, replace = TRUE, prob = c(0.2, 0.4, 0.3, 0.1)))/1e6
# 1 2 3 4
#0.200 0.400 0.299 0.100
В этом примере сумма вероятностей точно 1 (0.2 0.4 0.3 0.1), следовательно, это дает ожидаемое соотношение, но что, если вероятность не равна 1? Какой результат это даст? Я думал, что это приведет к ошибке, но это дает некоторое значение.
Когда вероятность суммируется с большим, чем 1.
table(sample(1:4, 1e6, replace = TRUE, prob = c(0.2, 0.5, 0.5, 0.1)))/1e6
# 1 2 3 4
#0.1544 0.3839 0.3848 0.0768
table(sample(1:4, 1e6, replace = TRUE, prob = c(0.2, 0.5, 0.5, 0.1)))/1e6
# 1 2 3 4
#0.1544 0.3842 0.3848 0.0767
Когда вероятность суммируется с меньшим, чем 1
table(sample(1:4, 1e6, replace = TRUE, prob = c(0.1, 0.1, 0.5, 0.1)))/1e6
# 1 2 3 4
#0.124 0.125 0.625 0.125
table(sample(1:4, 1e6, replace = TRUE, prob = c(0.1, 0.1, 0.5, 0.1)))/1e6
# 1 2 3 4
#0.125 0.125 0.625 0.125
Как мы можем видеть, многократный запуск дает результат, который не равен prob
, но результаты также не являются случайными. Как распределяются числа в этом случае? Где это задокументировано?
Я попытался выполнить поиск в Интернете, но не нашел никакой соответствующей информации. Я просмотрел документацию, в ?sample
которой есть
Необязательный аргумент prob может использоваться для задания вектора весов для получения элементов выбираемого вектора. Они не должны суммироваться с единицей, но они должны быть неотрицательными, а не полностью равными нулю. Если replace имеет значение true, метод псевдонимов Уолкера (Ripley, 1987) используется, когда имеется более 200 разумно вероятных значений: это дает результаты, несовместимые с результатами из R < 2.2.0.
Итак, он говорит, что prob
аргумент не должен суммироваться с 1, но не сообщает, что ожидается, когда он не суммируется с 1? Я не уверен, что мне не хватает какой-либо части документации. У кого-нибудь есть идеи?
Комментарии:
1. Они нормализуются для суммирования до единицы
2. Да, глядя на результат, я тоже так думаю, но не смог найти его нигде в документации.
3. возможно, использование «весов вероятности » вместо просто вероятностей в документах. Кажется уместным, что вектор весов используется, а не вероятности.
Ответ №1:
Хороший вопрос. В документах неясно, но на этот вопрос можно ответить, просмотрев исходный код.
Если вы посмотрите на код R, sample
всегда вызывает другую функцию R, sample.int
если вы передаете одно число x
в sample
, оно будет использоваться sample.int
для создания вектора целых чисел, меньших или равных этому числу, тогда как if x
— вектор, он используется sample.int
для генерации выборки целых чисел, меньших или равных length(x)
,затем использует это для подмножества x.
Теперь, если вы изучите функцию sample.int
, она выглядит так:
function (n, size = n, replace = FALSE, prob = NULL, useHash = (!replace amp;amp;
is.null(prob) amp;amp; size <= n/2 amp;amp; n > 1e 07))
{
if (useHash)
.Internal(sample2(n, size))
else .Internal(sample(n, size, replace, prob))
}
Это .Internal
означает, что любая выборка выполняется путем вызова скомпилированного кода, написанного на C: в данном случае это функция do_sample
, определенная здесь в src /main /random.c .
Если вы посмотрите на этот C-код, do_sample
проверяет, был ли ему передан prob
вектор. Если нет, то выполняется выборка в предположении о равных весах. Если prob
существует, функция гарантирует, что он числовой, а не NA . Если prob
проходит эти проверки, генерируется указатель на базовый массив double и передается другой функции в random.c вызывается FixUpProbs
, определяется здесь .
Эта функция проверяет каждый элемент prob
и выдает ошибку, если какие-либо элементы prob
не являются положительными конечными двойниками. Затем он нормализует числа, деля каждое на сумму всех. Поэтому нет никакого предпочтения для prob
суммирования до 1, присущего коду. То есть, даже если prob
на ваших входных данных сумма равна 1, функция все равно вычислит сумму и разделит на нее каждое число.
Поэтому параметр неправильно назван. Это должны быть «веса», как указывали другие здесь. Честно говоря, в документах говорится только, что это prob
должен быть вектор весов, а не абсолютных вероятностей.
Таким образом, поведение prob
параметра из моего чтения кода должно быть:
prob
может отсутствовать вообще, и в этом случае выборка по умолчанию имеет равные веса.- Если какое
prob
-либо из чисел меньше нуля, или бесконечно, или NA, функция выдаст. - Должна быть выдана ошибка, если какое-либо из
prob
значений нечисловое, поскольку они будут интерпретироваться какNA
в SEXP, переданном в код C. prob
должен иметь ту же длину,x
что и или выдает код C- Вы можете передать нулевую вероятность как один или несколько элементов
prob
, если вы указалиreplace=T
, если у вас есть хотя бы одна ненулевая вероятность. - Если вы укажете
replace=F
, количество запрашиваемых вами выборок должно быть меньше или равно количеству ненулевых элементов вprob
. По сути,FixUpProbs
он будет выдан, если вы попросите его выполнить выборку с нулевой вероятностью. - Допустимый
prob
вектор будет нормализован для суммирования до 1 и использоваться в качестве весов выборки.
В качестве интересного побочного эффекта такого поведения это позволяет вам использовать коэффициенты вместо вероятностей, если вы выбираете между 2 альтернативами, устанавливая probs = c(1, odds)
Комментарии:
1. Спасибо за очень хорошо проработанный ответ. Что касается вашего резюме в конце, в частности, пункта 5).
sample(1:4, 1, prob = c(0, 2, 3, 4))
похоже, работает так же хорошо, какtable(replicate(1e6, sample(1:4, 1, prob = c(0, 2, 3, 4))))
replace = FALSE
и с. Как упоминалось в документахThey need not sum to one, but they should be non-negative and not all zero
. Так что нормально иметь вероятность равной 0 для одного (или более, но не для всех) значения сreplace = FALSE
?2. Хорошая мысль @RonakShah. На самом деле, он будет выдавать только в том случае, если он вынужден выполнять выборку с вероятностью нуля. Вероятно, вы можете это сделать
sample(1:4, 2, prob = c(0, 0, 2, 3), replace = F)
, но если вы укажете n = 3, то после того, как в выборке присутствуют 3 и 4, он попытается выполнить выборку 1 или 2 с вероятностью 0 и выбросить. В настоящее время не могу это проверить…3. @RonakShah Я проверил это сейчас, и это действительно поведение. Ответ обновлен.
Ответ №2:
Как уже упоминалось, веса нормализуются для суммирования до 1, что можно продемонстрировать:
> x/sum(x)
[1] 0.15384615 0.38461538 0.38461538 0.07692308
Это соответствует вашим смоделированным табличным данным:
# 1 2 3 4
#0.1544 0.3839 0.3848 0.0768