numpy:从给定范围生成组合的有效方法
我有一个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来构建两个数组的所有组合的数组
我需要做 几百万遍 。
我的问题:是否有 更好/有效的 方法来做到这一点?
-
我认为您正在寻找的是
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格式。