kAIST
@kAIST

Как сделать random с неравномерным распределением в Python?

Есть некий список, из которого случайным образом нужно выбирать элемент. Но вероятность того что выпадет элемент в начале списка должна быть выше чем в конце.
Как это реализовать на Python?
  • Вопрос задан
  • 3442 просмотра
Пригласить эксперта
Ответы на вопрос 2
@Roman_Kh
Сначала определите предельно конкретно, что означает "в начале вероятность выше, чем в конце".
После чего сможете написать свою функцию распределения. Например, в вашем списке 4 элемента и вероятности распределены так: 60, 25, 12, 3, то есть 60% - для 1-го элемента, 25% - для 2-го и так далее.
Тогда
your_data_list = [...]
probabilities_list=[60, 85, 97, 100]
rnd = random.uniform(1, 100)
idx = -1
idx_found = False
while idx < len(probabilities_list) and not idx_found:
  idx += 1
  idx_found = rnd <= probabilities_list[idx]
your_random = your_data_list[idx]

Однако, это очень медленный способ (и к тому же не лишенный некоторых проблем).

Можно сделать быстрее и короче с помощью модуля bisect:
idx = bisect.bisect_right(probabilities_list, rnd)
Этот вариант будет заметно быстрее (иногда, правда, на 20%, но иногда и в 3.5 раза).

Но правильнее всего использовать numpy:
numpy.random.choice(your_data_list, size=N, p=prb_list)

Это будет раз в 10 быстрее.
При этом prb_list должен содержать именно вероятности появления каждого элемента, т.е. для вышеприведенного примера [0.6, 0.25, 0.12, 0.03]
Ответ написан
@nirvimel
Сделал справочную таблицу по функциям модуля random, которые генерируют значения с заданным вероятностным распределением.

ФункцияВероятностное распределение
random.uniform(a, b)Uniform distribution
(Непрерывное равномерное распределение)
random.triangular(low, high, mode)Triangular distribution
random.betavariate(alpha, beta)Beta distribution
(Бета-распределение)
random.expovariate(lambd)Exponential distribution
(Экспоненциальное распределение)
random.gammavariate(alpha, beta)Gamma distribution
(Гамма-распределение)
random.gauss(mu, sigma)
random.normalvariate(mu, sigma)
Normal distribution
(Нормальное распределение)
random.lognormvariate(mu, sigma)Log-normal distribution
(Логнормальное распределение)
random.vonmisesvariate(mu, kappa)Von_Mises_distribution
random.paretovariate(alpha)Pareto distribution
(Распределение Парето)
random.weibullvariate(alpha, beta)Weibull distribution
(Распределение Вейбулла)


Что касается вопроса, то, в зависимости от формы графика, которой вы добиваетесь, вам может подойти одно из этих:
  1. random.triangular(0., 1., 0.)
  2. random.expovariate(1.) (параметр lambd характеризует "наклон" графика, значение 1. выбрано произвольно)
  3. math.fabs(random.gauss(0., 1.)) (параметр sigma характеризует "наклон" графика, значение 1. выбрано произвольно)
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы