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有你覆蓋。