Как создать ограниченный случайный массив на основе среднего значения и стандартного отклонения другого массива? - PullRequest
2 голосов
/ 18 апреля 2019

У меня есть массив X, содержащий R строки и C столбцы. Я хочу создать новый массив с именем a_array, где каждый элемент будет генерироваться случайным образом на основе среднего значения и стандартного отклонения соответствующей ему строки в X. Какой самый питонный и эффективный способ сделать это с помощью Numpy?

В настоящее время я использую вложенный цикл для генерации поэлементных чисел.

a_array = np.zeros(shape=(a_size, X.shape[0]))
for i in range(a_size):
    for j in range(X.shape[0]):
        a_array[i][j] = np.random.randint(low=X[i].mean()-X[i].std(), high=X[i].mean()+X[i].std())

РЕДАКТИРОВАТЬ: Извините, я кое-что забыл, но я также хотел бы убедиться, что каждая строка a_array содержит уникальные элементы (ни в одной строке нет повторяющихся элементов). До сих пор я не мог придумать, как этого добиться.

Ответы [ 2 ]

1 голос
/ 18 апреля 2019

Частично векторизовано

Мы можем сократить его до одного цикла -

m,s = X[:a_size].mean(1),X[:a_size].std(1)
L = (m-s).astype(int)
H = (m+s).astype(int)
out = np.empty((a_size,X.shape[0]),dtype=int)
for i,(l,h) in enumerate(zip(L,H)):
    out[i] = np.random.choice(np.arange(l,h),X.shape[0],replace=False)

Основная идея:

  1. Вычислить средние и стандартные значения вдольвторая осьПеред этим нам нужно нарезать X, чтобы ограничить его a_size строками, если a_size не является количеством строк в X.

  2. В оригиналезацикленная версия, мы используем random.randint со средним-стандартным и средним + стандартным в качестве пределов.Таким образом, для предложенной версии получите нижний и верхний пределы, используя средние и стандартные значения из шага № 1.

  3. Запустите цикл с np.random.choice(np.arange(l,h),X.shape[0],replace=False) с этими низкими и высокими значениями для настройкидиапазон значений на выбор и выбор случайных значений размером X.shape[0] и уникальных значений с replace=False.

полностью векторизация

Мы могли бы сделать его полностью векторизованнымс трюком, как указано в 1 & 2 , чтобы дать нам что-то вроде следующего, который заменяет зацикленный шаг, перечисленный ранее:

R = H-L
MX = R.max()
n = X.shape[0]
unqIDs = np.random.rand(len(L),MX).argpartition(axis=1,kth=n)[:,:n]
out = unqIDs%R[:,None] + L[:,None]

Обратите внимание, что это будет иметьбольше места в памяти.

1 голос
/ 18 апреля 2019

Просто удалите уровень цикла for и сгенерируйте вектор случайных чисел, чтобы заменить всю строку вместо замены на позицию за раз

a_array = np.zeros(shape=(a_size, X.shape[0]))
for i in range(a_size):
    a_array[i] = np.random.randint(\
                      low=X[i].mean()-X[i].std(),\ 
                      high=X[i].mean()+X[i].std(),\
                      size=(1,a_array.shape[1]))
...