Создать двоичную случайную матрицу с верхним и нижним пределом числа единиц в каждой строке? - PullRequest
1 голос
/ 15 апреля 2020

Я хочу создать двоичную матрицу чисел с M строками и N столбцами. Каждая строка должна иметь сумму <= <code>p и> = q. Другими словами, каждая строка должна содержать не более p и не менее q единиц.

Это код, который я использовал.

import numpy as np
def randbin(M, N, P):  
    return np.random.choice([0, 1], size=(M, N), p=[P, 1 - P])

MyMatrix = randbin(200, 7, 0.5)

Обратите внимание, что в строке 0 все нули:

x

Я заметил, что в некоторых строках есть все нули, а в некоторых - все. Как я могу изменить это, чтобы получить то, что я хочу? Есть ли эффективный способ достижения этого решения?

Ответы [ 2 ]

2 голосов
/ 16 апреля 2020

Вы можете сгенерировать случайное число в [q, p] для каждой строки, а затем установить столько случайных чисел в каждой строке. Если под эффективным вы подразумеваете векторизацию, то да, есть эффективный путь. Хитрость заключается в том, чтобы моделировать выборку без замены по одной оси, но по другой. Это можно сделать с помощью np.argsort. Вы можете выбрать переменное число индексов, превратив случайный вектор в маску.

def randbin(m, n, p, q):
    # output to assign ones into
    result = np.zeros((m, n), dtype=bool)
    # simulate sampling with replacement in one axis
    col_ind = np.argsort(np.random.random(size=(m, n)), axis=1)
    # figure out how many samples to take in each row
    count = np.random.randint(p, q + 1, size=(m, 1))
    # turn it into a mask over col_ind using a clever broadcast
    mask = np.arange(n) < count
    # apply the mask not only to col_ind, but also the corresponding row_ind
    col_ind = col_ind[mask]
    row_ind = np.broadcast_to(np.arange(m).reshape(-1, 1), (m, n))[mask]
    # Set the corresponding elements to 1
    result[row_ind, col_ind] = 1
    return result

Выбор сделан таким образом, что каждый прогон равных значений в row_ind находится между p и q элементы длинные. Соответствующие элементы col_ind уникальны и равномерно распределены в каждой строке.

Альтернативой является @ Prunes solution . Требуется np.argsort для независимого перемешивания строк, поскольку np.random.shuffle будет хранить строки вместе:

def randbin(m, n, p, q):
    # make the unique rows
    options = np.arange(n) < np.arange(p, q + 1).reshape(-1, 1)
    # select random unique row to go into each output row
    selection = np.random.choice(options.shape[0], size=m, replace=True)
    # perform the selection
    result = options[selection]
    # create indices to shuffle each row independently
    col_ind = np.argsort(np.random.random(result.shape), axis=1)
    row_ind = np.arange(m).reshape(-1, 1)
    # perform the shuffle
    result = result[row_ind, col_ind]
    return result
2 голосов
/ 15 апреля 2020

Хорошо, тогда: равномерное распределение достаточно просто. Давайте возьмем этот случай с [2,5] 1 s. Используйте список допустимых комбинаций:

[ [1, 1, 0, 0, 0, 0],
  [1, 1, 1, 0, 0, 0],
  [1, 1, 1, 1, 0, 0],
  [1, 1, 1, 1, 1, 0] ]

Для каждой из ваших строк выберите случайный элемент из этих четырех, а затем shuffle его. Вот твой ряд.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...