Стандартная библиотека Scala не имеет эквивалента np.random.choice
, но ее создание не должно быть слишком сложным, в зависимости от того, какие опции / функции вы хотите эмулировать.
Вот, например, способ получения бесконечного Stream
отправленных предметов с вероятностью взвешивания любого одного предмета относительно других.
def weightedSelect[T](input :(T,Int)*): Stream[T] = {
val items :Seq[T] = input.flatMap{x => Seq.fill(x._2)(x._1)}
def output :Stream[T] = util.Random.shuffle(items).toStream #::: output
output
}
При этом каждому элементу ввода присваивается множитель. Таким образом, чтобы получить бесконечный псевдослучайный выбор символов c
и v
, при этом c
поднимается на 3/5 доли времени, а v
- на 2/5 доли времени:
val cvs = weightedSelect(('c',3),('v',2))
Таким образом, грубый эквивалент примера np.random.choice(aa_milne_arr,5,p=[0.5,0.1,0.1,0.3])
будет:
weightedSelect("pooh"-> 5
,"rabbit" -> 1
,"piglet" -> 1
,"Christopher" -> 3).take(5).toArray
Или, возможно, вам нужно лучшее (менее псевдо) случайное распределение, которое может быть сильно однобоким.
def weightedSelect[T](items :Seq[T], distribution :Seq[Double]) :Stream[T] = {
assert(items.length == distribution.length)
assert(math.abs(1.0 - distribution.sum) < 0.001) // must be at least close
val dsums :Seq[Double] = distribution.scanLeft(0.0)(_+_).tail
val distro :Seq[Double] = dsums.init :+ 1.1 // close a possible gap
Stream.continually(items(distro.indexWhere(_ > util.Random.nextDouble())))
}
Результат по-прежнему бесконечен Stream
указанных элементов, но переданные аргументы немного отличаются.
val choices :Stream[String] = weightedSelect( List("this" , "that")
, Array(4998/5000.0, 2/5000.0))
// let's test the distribution
val (choiceA, choiceB) = choices.take(10000).partition(_ == "this")
choiceA.length //res0: Int = 9995
choiceB.length //res1: Int = 5 (not bad)