Взвешенный numpys random.выбор для интервалов

#python #numpy #random

#python #numpy #Случайный

Вопрос:

Я хочу создать псевдослучайно массив значений транзакций из полуоткрытых интервалов, например [1,5), [5,10), [10,25) , и так далее. Каждое число в интервале имеет одинаковую вероятность выбора, но я хочу настроить вероятность получения одних интервалов по сравнению с другими. Поток должен выглядеть следующим образом:

 1: Pick any of the defined intervals > Pick a random number in the interval > Append number in array
2: Pick any of the defined intervals > Pick a random number in the interval > Append number in array
...
n: Pick any of the defined intervals > Pick a random number in the interval > Append number in array
  

Мой код:

 import numpy as np
# set interval limits
a,b,c,d,e,f,g,h,i,j = 1,5,10,25,50,100,200,300,500,1000
# start picking random numbers
np.random.seed(33)
trx_value = np.random.choice([np.random.uniform(a,b), 
                              np.random.uniform(b,c),
                              np.random.uniform(c,d),
                              np.random.uniform(d,e),
                              np.random.uniform(e,f),
                              np.random.uniform(f,g),
                              np.random.uniform(g,h),
                              np.random.uniform(h,i),
                              np.random.uniform(i,j)], 20, 
                              p=[0.1, 0.15, 0.2, 0.2, 0.15, 0.1, 0.05, 0.03, 0.02])
trx_value
  

Кажется, что он работает по-другому, так как результат не отображает уникальность в значениях, которые я ожидал:

 > array([  8.22611761,   8.22611761, 127.05325134,   8.22611761,
>        266.53172436,  35.43526485,  35.43526485,  88.57366253,
>        127.05325134,  12.38946805, 266.53172436, 127.05325134,
>         12.38946805,  35.43526485, 127.05325134,  12.38946805,
>        266.53172436,   8.22611761])
  

Кажется, он делает что-то вроде этого:

 1: For each interval, pick a random number > Store this number in a pool
2: Pick a random number from the pool > Append number in array
...
n: Pick a random number from the pool > Append number in array
  

Я уверен, что это проблема мышления, но я хочу знать, возможно ли это без использования for цикла

Ответ №1:

Поскольку все дистрибутивы, которые вы хотите выбрать, являются однородными, я бы предложил следующую настройку.

 interval_p = np.array([0.1, 0.15, 0.2, 0.2, 0.15, 0.1, 0.05, 0.03, 0.02])
interval_lo = np.array([1,5,10,25,50,100,200,300,500])
interval_hi = np.concatenate([lo[1:], [1000]])
interval_width = interval_hi - interval_lo

n = 20
c = np.random.choice(len(interval_p), p=interval_p, size=n)
results = interval_lo[c]   np.random.uniform(size=n) * interval_width[c]
  

Это работает, потому что мы можем масштабировать равномерное распределение r на [0, 1] любое равномерное распределение при [a, b] использовании a r*(b-a) .

Комментарии:

1. Вы можете просто создать interval = np.array([1,5,10,25,50,100,200,300,500,1000]) , а затем иметь interval_width = np.diff(interval) и использовать interval[:-1] вместо interval_lo . Делает его немного более читаемым.

2. Спасибо! Это работает, и с рекомендациями @DanielF еще более читабельно. Вы можете сказать, когда имеете дело с парнями с сильным математическим образованием 🙂