numpy:从给定范围生成组合的有效方法

发布于 2021-01-29 19:05:40

我有一个n维数组,如下所示:

np.array([[0,3],[0,3],[0,10]])

在此数组中,元素表示低值和高值。例如:[0,3][0,1,2,3]

我需要使用上面给出的范围生成所有值的组合。例如我想要[0,0,0], [0,0,1] ... [0,1,0] ... [3,3,10]

我已经尝试了以下方法来获得想要的东西:

ds = np.array([[0,3],[0,3],[0,10]])
nItems = int(reduce(lambda a,b: a * (b[1] - b[0] + 1), ds, 1))
myCombinations = np.zeros((nItems,))
nArrays = []
for x in range(ds.shape[0]):
    low = ds[x][0]
    high= ds[x][1]
    nitm = high - low + 1
    ar = [x+low for x in range(nitm) ]
    nArrays.append(ar)

myCombinations = cartesian(nArrays)

笛卡尔函数取自使用numpy来构建两个数组的所有组合的数组

我需要做 几百万遍

我的问题:是否有 更好/有效的 方法来做到这一点?

关注者
0
被浏览
50
1 个回答
  • 面试哥
    面试哥 2021-01-29
    为面试而生,有面试问题,就找面试哥。

    我认为您正在寻找的是np.mgrid。不幸的是,这会以与所需格式不同的格式返回数组,因此您需要进行一些后期处理:

    a = np.mgrid[0:4, 0:4, 0:11]     # All points in a 3D grid within the given ranges
    a = np.rollaxis(a, 0, 4)         # Make the 0th axis into the last axis
    a = a.reshape((4 * 4 * 11, 3))   # Now you can safely reshape while preserving order
    

    说明

    np.mgrid在N维空间中为您提供了一组网格点。让我尝试用一​​个较小的示例来说明这一点,以使事情更清楚:

    >>> a = np.mgrid[0:2, 0:2]
    >>> a
    array([[[0, 0],
            [1, 1]],
    
           [[0, 1],
            [0, 1]]])
    

    由于我指定了两组范围0:2, 0:2,因此我得到了2D网格。什么mgrid返回是x的值和对应于在二维空间中的网格点(0,0),(0,1),(1,0)和(1,1)的y的值。a[0]告诉您四个点的x值是a[1]什么,并告诉您y值是什么。

    但是,您真正想要的是我已经写出的实际网格点列表,而不是分别列出这些点的x和y值。首先的直觉是根据需要调整数组的形状:

    >>> a.reshape((4, 2))
    array([[0, 0],
           [1, 1],
           [0, 1],
           [0, 1]])
    

    但是显然这是行不通的,因为它可以有效地重塑展平的数组(通过按顺序读取所有元素而获得的数组),而这并不是您想要的。

    您要做的是向下看的 第三a,并创建一个数组:

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

    上面写着“首先告诉我第一个点(x1,y1),然后第二个点(x2,y2),…”,依此类推。也许可以用一个数字更好地解释这一点。这是什么a样子:

                    you want to read
                    in this direction
                     (0, 0)   (0, 1)
                       |        |
                       |        |
                       v        v
    
              /        0--------0            +----> axis0
     x-values |       /|       /|           /|
              |      / |      / |    axis1 / |
              \     1--------1  |         L  |
                    |  |     |  |            v
              /     |  0-----|--1           axis2
     y-values |     | /      | /
              |     |/       |/
              \     0--------1
    
                    |        |
                    |        |
                    v        v
                  (1, 0)   (1, 1)
    

    np.rollaxis为您提供了一种方法。np.rollaxis(a, 0, 3)在上面的示例中,“将第0(或 最外 )轴设为最后(或 最内
    )轴。(注意:此处实际上仅存在轴0、1和2。因此说:“将第0根轴发送到第3根轴)位置”是告诉python将第0个轴放在最后一个轴之后的一种方法。您可能还想阅读一下。

    >>> a = np.rollaxis(a, 0, 3)
    >>> a
    array([[[0, 0],
            [0, 1]],
    
           [[1, 0],
            [1, 1]]])
    

    这开始看起来像您想要的,除了有一个额外的数组维。我们想要合并尺寸0和1,以获得仅一个网格点数组。但是,既然展平的数组以您期望的方式读取,您就可以安全地对其重塑形状以得到所需的结果。

    >>> a = a.reshape((4, 2))
    >>> a
    array([[0, 0],
           [0, 1],
           [1, 0],
           [1, 1]])
    

    3D版本执行相同的操作,不同之处在于,我无法确定其数字,因为它采用4D格式。



知识点
面圈网VIP题库

面圈网VIP题库全新上线,海量真题题库资源。 90大类考试,超10万份考试真题开放下载啦

去下载看看