Python Random Array из 0 и 1

Я хочу случайным образом произвести array из n одни и m нули.

Я думал об этом решении:

  1. произвести массивnp.ones)
  2. создать массив нулей (np.zeros)
  3. объединить их в один массив (np.hstack)
  4. перемешать полученный массив (np.random.shuffle)

Кажется, не является естественным решением. Некоторые питонские идеи?

4 ответа

Решение

Ваше решение кажется разумным. В нем точно указано, что он делает, и делает это четко.

Давайте сравним вашу реализацию:

a = np.hstack((np.ones(n), np.zeros(m)))
np.random.shuffle(a)

... с очевидной альтернативой:

a = np.ones(n+m)
a[:m] = 0
np.random.shuffle(a)

Это может сэкономить немного времени, не выделяя и не перемещая фрагменты данных, но это требует немного больше мысли, чтобы понять.

И делать это в Python, а не в NumPy:

a = np.array([1]*n + [0]*m)
np.random.shuffle(a)

... может быть немного более кратким, но он выглядит менее идиоматически NumPy (так же, как np.array([1]*n) менее идиоматичен, чем np.ones(n)), и это будет медленнее и использовать больше памяти без веской причины. (Вы можете улучшить память, используя np.fromiter, но тогда это довольно явно не будет более кратким.)

Конечно, если вы делаете это более одного раза, реальный ответ состоит в том, чтобы выделить это в функцию. Тогда название функции объяснит, что она делает, и почти любое решение, которое не слишком мучительно, будет довольно легко понять...

Я бы сделал массив из n единиц и m нулей, как

a = np.array([1] * n + [0] * m)

Тогда я бы позвонил np.random.shuffle() в теме.

Я думаю, что ваше решение подходит, потому что оно читаемо и питонно. Вы не сказали, являются ли память или производительность соображениями. Возможно, что np.random.shuffle так же хорош, как O(m + n), но другие ответы предполагают, что он делает больше, чем один проход, чтобы перемешать значения. Вы можете сделать это в O (m + n) только с одним проходом и без затрат памяти, как это:

import random
m = 600 # zeros
n = 400 # ones

result = []
while m + n > 0:
    if (m > 0 and random.random() < float(m)/float(m + n)):
        result.append(0)
        m -= 1
    else:
        result.append(1)
        n -= 1

Использование numpy.random.permutation:

a = numpy.random.permutation([1] * n + [0] * m)

или, используя массивы вместо исходного списка:

a = numpy.random.permutation(numpy.concatenate(np.ones(n), np.zeros(m)))

(Я не знаю достаточно о numpy прокомментировать разницу между concatenate а также hstack; похоже, они дают одинаковые результаты.)

Другие вопросы по тегам