Я хочу рисовать из дискретного распределения.
У меня есть матрица pi, которая состоит из векторов вероятностей (с тем же числом столбцов и суммой каждой строки равно 1).
В Python я могу сделать следующее
cumsumpi = cumsum(pi, axis = 1)
[bisect.bisect(k, random.rand()) for k in cumsumpi]
чтобы получить вектор дроби по вероятности, заданной pi.
Теперь я хочу воспроизвести это с помощью R. Я знаю, что в R есть функция "sample", но кажется, что он использует какой-то другой алгоритм, а затем делит пополам, поэтому я получаю разные рисунки, хотя я использую тот же set.seed() в обоих случаях.
Я использовал rpy2, чтобы получить точно такие же случайные дроби в Python, что и в R. Например,
вместо random.rand(), я использовал [bisect.bisect(k, asarray (robjects.r('runif (1)'))) для k в cumsumpi]
Пожалуйста, дайте мне знать, есть ли другая функция, чем образец в R, которые делают то же самое.
-Joon
отредактирован: Мне удалось воспроизвести точно такие же розыгрыши со следующим, но это было медленно.
cumsumpi = t(apply(pi, 1, cumsum))
getfirstindx = function(cumprobs) {
return(which(cumprobs > runif(1))[1])
}
apply(cumsumpi, 1, getfirstindx)
здесь есть альтернативный подход, который позволяет избежать использования apply и вместо этого векторизовать операцию. Первоначальные проверки показывают, что он в два раза быстрее, но нужно изучить более подробно.
cumsumpi = t(apply(pi, 1, cumsum));
u = runif(nrow(cumsumpi));
max.col((cumsumpi > u) * 1, "first")
чтобы ускорить его, можно было бы подумать о векторизации операции вычисления совокупных сумм столбцов для каждой строки. сообщите мне, был ли этот шаг узким местом, запустив профайлер вашего R-кода.
Я не опубликовал его, но то, что я закончил, было довольно похоже:
cumsumpi = t(apply(pi, 1, cumsum))
1 + rowSums(cumsumpi > runif(nrow(pi)))
Скорость была почти такой же, как ваш код. Если бы я знал о max.col, я бы использовал это.
И после вашего предложения, я векторизовал вещь cumsum, и это дало мне нетривиальное увеличение скорости. Спасибо.
-Joon
То, что я искал, было findInterval - найти интервальные номера или индексы.:)
Я не могу согласовать заголовок вопроса с телом вопроса - в любом случае здесь функция R идентична функции bisect python:
Пакет gtool * s имеет двоичную функцию поиска ** binsearch *, которая почти идентична bisect python, например,
# search for 25 in the range 0 through 100
> binseaerch(fun = function(x) x - 25, range=c(0, 100))
$call
binsearch(fun = function(x) x - 25, range = c(0, 100))
$numiter
[1] 2
$flag
[1] "Found"
$where
[1] 25
$value
[1] 0