0

这在一定程度上关系到Numpy: cartesian product of x and y array points into single array of 2D points任意维数组任意三维坐标的笛卡尔乘积

我在寻找一个简洁的方式来创建两个阵列,任意维度的笛卡尔积。

实例:

现有螺纹类似的,我想

x = numpy.array([1,2,3]) #ndim 1 
y = numpy.array([4,5]) #ndim 1 
cartesian_product(x,y) == numpy.array([[[1, 4], 
             [2, 4], 
             [3, 4]], 
             [[1, 5], 
             [2, 5], 
             [3, 5]]]) #ndim "2" = ndim x + ndim y 

所得阵列是二维因为[1,4],[2,4]等是坐标,并因此不是真正的维度。总而言之,将x/y写为[[1],[2],[3]]可能会更好。

以上是等于

numpy.dstack(numpy.meshgrid(x,y)) 

但我也想

x2 = numpy.array([[1,1], [2,2], [3,3]]) #ndim "1", since [1, 1] is a coordinate 
cartesian_product(x2,y) == numpy.array([[[1, 1, 4], 
             [2, 2, 4], 
             [3, 3, 4]], 

             [[1, 1, 5], 
             [2, 2, 5], 
             [3, 3, 5]]]) #ndim 2 = ndim x2 + ndim y 


y2 = numpy.array([[10, 11], [20, 21]]) #ndim 1 
(cartesian_product(x2, y2) == 
numpy.array([[[1, 1, 10, 11], 
       [2, 2, 10, 11], 
       [3, 3, 10, 11]], 

      [[1, 1, 20, 21], 
       [2, 2, 20, 21], 
       [3, 3, 20, 21]]])) #ndim x2 + ndim y2 

x3 = numpy.array([[[1, 2], [3, 4]], [[5, 6], [7, 8]]]) #ndim 2 
(cartesian_product(x3, y) == 
numpy.array([[[[1, 2, 4], [3, 4, 4]], [[5, 6, 4], [7, 8, 4]]], 
      [[[1, 2, 5], [3, 4, 5]], [[5, 6, 5], [7, 8, 5]]]]) #ndim 3 

为了形象我想要做的事: 正如我所说的,[0,0],[ 0,1],[1,1],[1,0]]应该被解释为坐标的一维列表,其对应于一条线。如果我用[1,2,3,4]做一个笛卡尔乘积,我就沿着z方向挤压这条线,变成一个曲面(即2维)。但是现在阵列当然是三维的。

我想我可以找到解决这个循环,但有没有办法用numpy/scipy工具来实现这一点?

+0

我不明白你的意思是“坐标”。第一个示例中的结果数组是三维的。如果你将它输入到numpy中,它会有ndim 3.同样,你所有的例子x2,y2,x3都有比你想象的更多的维度。 – BrenBarn

+0

当然[[1,1],[2,2]]是二维数组。但是在我所寻找的笛卡尔积函数中,它基本上是一维的,因为它只是一个坐标列表[coord1,coord2]。 [[coord11,coord12],[coord21,coord22]]将是“2”维的,即使它的数组是2 + 1维的。 如果我试图说明我的问题,假设我有xy定义的曲线,它将是一个坐标列表,但一条线基本上是一维的,这可能会更容易。我试图做的是在另一个维度挤压它。 – mueslo

回答

1

内存有效的方式进行广播分配:

def cartesian_product(x, y): 
    if x.ndim < 2: 
     x = np.atleast_2d(x).T 
    if y.ndim < 2: 
     y = np.atleast_2d(y).T 

    sx, sy = x.shape, y.shape 
    sz = sy[:-1] + sx[:-1] + (sy[-1] + sx[-1],) 
    z = np.empty(sz, np.result_type(x, y)) 

    # Broadcasted assignment 
    z[...,:sx[-1]] = x 
    z[...,sx[-1]:] = y.reshape(sy[:-1] + (x.ndim-1)*(1,) + (sy[-1],)) 

    return z 

如果你需要在细节上广播,this page有你覆盖。