Prodotto cartesiano per riga tra un array 1d e un array 2d

Sep 22 2020

Penso che mi manchi qualcosa di ovvio. Voglio trovare un prodotto cartesiano di arr1 (una matrice NumPy 1D), e le RIGHE di arr2 (una matrice NumPy 2d). Quindi, se arr1 ha 4 elementi e arr2 ha forma (5,2), l'output dovrebbe avere forma (20,3). (vedi sotto)

import numpy as np

arr1 = np.array([1, 4, 7, 3])

arr2 = np.array([[0, 1],
                 [2, 3], 
                 [4, 5],
                 [4, 0],
                 [9, 9]])

L'output desiderato è:

arr3 = np.array([[1, 0, 1],
                 [1, 2, 3], 
                 [1, 4, 5],
                 [1, 4, 0],
                 [1, 9, 9],
              
                 [4, 0, 1],
                 [4, 2, 3], 
                 [4, 4, 5],
                 [4, 4, 0],
                 [4, 9, 9],
               
                 [7, 0, 1],
                 [7, 2, 3], 
                 [7, 4, 5],
                 [7, 4, 0],
                 [7, 9, 9],
              
                 [3, 0, 1],
                 [3, 2, 3], 
                 [3, 4, 5],
                 [3, 4, 0],
                 [3, 9, 9]])

Ho provato a usare Transpose e Reshape con codice come np.array (np.meshgrid (arr1, arr2)), ma ancora senza successo.

Spero che la soluzione possa essere generalizzata perché devo anche affrontare situazioni come questa: Ottieni tutte le combinazioni delle RIGHE di un array 2d (10,2) e delle RIGHE di un array 2d (20, 5) per ottenere un matrice di output (200,7).

Risposte

1 Ehsan Sep 22 2020 at 09:48

Ecco una soluzione vettorializzata che funziona anche per il tuo caso generale:

arr1 = np.array([[1, 4], 
                 [7, 3]])

arr2 = np.array([[0, 1],
                 [2, 3], 
                 [4, 5],
                 [4, 0],
                 [9, 9]])

np.hstack((np.repeat(arr1,len(arr2),0),np.stack((arr2,)*len(arr1)).reshape(-1,arr2.shape[1])))

output di forma (2,2)* (5,2)-> (10,4):

[[1 4 0 1]
 [1 4 2 3]
 [1 4 4 5]
 [1 4 4 0]
 [1 4 9 9]
 [7 3 0 1]
 [7 3 2 3]
 [7 3 4 5]
 [7 3 4 0]
 [7 3 9 9]]
1 RajeshBhat Sep 22 2020 at 09:27

Puoi usare hstack per aggiungere colonne ad arr2 e vstack per ottenere l'array finale.

np.vstack(np.apply_along_axis(lambda x: np.hstack([np.repeat(x[0], arr2.shape[0]).reshape(-1, 1), 
                                                   arr2]), 
                              1, 
                              arr1[:, None]))
user109387 Sep 22 2020 at 08:55

Penso che questo dovrebbe farlo:

import numpy as np

arr0 = np.array([1, 4, 7, 3])
arr1 = np.reshape(arr0, (len(arr0),1))
arr2 = np.array([[0, 1],
                 [2, 3], 
                 [4, 5],
                 [4, 0],
                 [9, 9]])

r1,c1 = arr1.shape
r2,c2 = arr2.shape
arrOut = np.zeros((r1,r2,c1+c2), dtype=arr1.dtype)
arrOut[:,:,:c1] = arr1[:,None,:]
arrOut[:,:,c1:] = arr2
arrOut.reshape(-1,c1+c2)

L'output è:

array([[1, 0, 1],
       [1, 2, 3],
       [1, 4, 5],
       [1, 4, 0],
       [1, 9, 9],
       [4, 0, 1],
       [4, 2, 3],
       [4, 4, 5],
       [4, 4, 0],
       [4, 9, 9],
       [7, 0, 1],
       [7, 2, 3],
       [7, 4, 5],
       [7, 4, 0],
       [7, 9, 9],
       [3, 0, 1],
       [3, 2, 3],
       [3, 4, 5],
       [3, 4, 0],
       [3, 9, 9]])
Param Sep 22 2020 at 13:24

Pulito e facile

In base a come hai visualizzato l'output desiderato in questione. Ha forma di (4,5,3). se è il caso, la soluzione è sotto e, in caso contrario, modifica l'array di output nella tua domanda.

import numpy as np
 arr1 = np.array([1, 4, 7, 3])
 
arr2 = np.array([[0, 1],
                 [2, 3], 
                 [4, 5],
                 [4, 0],
                 [9, 9]])
arr3 = np.broadcast_to(arr1[:, np.newaxis, np.newaxis], (4,5,1))
print(arr3.shape)
(4, 5, 1)
print(arr3)
[[[1]
  [1]
  [1]
  [1]
  [1]]

 [[4]
  [4]
  [4]
  [4]
  [4]]

 [[7]
  [7]
  [7]
  [7]
  [7]]

 [[3]
  [3]
  [3]
  [3]
  [3]]]
arr4 =  np.broadcast_to(arr2[np.newaxis, :, :], (4,5,2))
print(arr4.shape)
(4, 5, 2)
print(arr4)
[[[0 1]
  [2 3]
  [4 5]
  [4 0]
  [9 9]]

 [[0 1]
  [2 3]
  [4 5]
  [4 0]
  [9 9]]

 [[0 1]
  [2 3]
  [4 5]
  [4 0]
  [9 9]]

 [[0 1]
  [2 3]
  [4 5]
  [4 0]
  [9 9]]]
arr5 = np.concatenate([arr3, arr4], axis=-1)
print(arr5.shape)
(4, 5, 3)
print(arr5)
[[[1 0 1]
  [1 2 3]
  [1 4 5]
  [1 4 0]
  [1 9 9]]

 [[4 0 1]
  [4 2 3]
  [4 4 5]
  [4 4 0]
  [4 9 9]]

 [[7 0 1]
  [7 2 3]
  [7 4 5]
  [7 4 0]
  [7 9 9]]

 [[3 0 1]
  [3 2 3]
  [3 4 5]
  [3 4 0]
  [3 9 9]]]