【问题标题】:Generate binary random matrix with upper and lower limit on number of ones in each row?生成每行中具有上限和下限的二进制随机矩阵?
【发布时间】:2020-07-27 19:47:22
【问题描述】:

我想生成具有M 行和N 列的数字二进制矩阵。每行的总和必须为 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 行全为零:

我注意到有些行全为零,有些行全为 1。我怎样才能修改它以获得我想要的?是否有实现此解决方案的有效方法?

【问题讨论】:

  • 请澄清问题。我不明白“甚至传播(如果允许)或类似的......”您使用“随机”一词而没有描述在给定限制下的含义。由于没有明确的示例或描述,我完全不清楚哪种流程可以解决您的需求。
  • 我已经改写了这个问题。
  • 有了 [p,q] 约束,您需要什么样的分布。例如,给定 6 列中的 [2,5],您期望总和的分布是什么?它是均匀的、正态的还是 [0,7] 正态分布的一部分?
  • 均匀分布和正态分布都可以解决我的问题。感谢您提出这个问题。
  • 别忘了选择答案

标签: python numpy random


【解决方案1】:

您可以在 [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 中每个相等值的运行长度在pq 元素之间。 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】:

    好的,那么:均匀分布很容易。让我们以需要 [2,5] 1s 的情况为例。使用允许的组合列表:

    [ [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 它。有你的行。

    【讨论】:

    • 太棒了。这可以工作。谢谢你。如果均匀分布,代码会发生什么变化。
    • 实现起来并不像我预期的那么简单。我已将您的建议的实施添加到我的回答中。
    猜你喜欢
    • 2022-12-03
    • 2015-11-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-08-31
    • 2023-04-08
    • 2020-03-16
    • 2022-01-03
    相关资源
    最近更新 更多