come unire in modo efficiente due 3d-array sulla 2a dimensione?

Aug 27 2020

Diciamo che ho due array tridimensionali (a & b) di forma (1.000.000, ???, 50), (??? = vedi sotto).

Come unirli, in modo che il risultato sia (1.000.000, {forma della seconda dimensione di a + b}, 50)?

Ecco gli esempi, come puoi vedere di seguito: (sono possibili anche np.arrays)

EDIT: aggiunto codice utilizzabile, scorrere ^^

[ #a
     [           
                 ],
     [ 
       [1  2  3]
                 ],
     [ 
       [0  2    7]
       [1  Nan  3]
                 ],
     [ 
       [10   0  3]
       [NaN  9  9]
       [10 NaN  3]
                 ],
     [ 
       [8  2  0]
       [2  2  3]
       [8  1  3]
       [1  2  3]
                 ],
     [ 
       [0  2  3]
       [1  2  9]
       [1  2  3]
       [1  0  3]
       [1  2  3]
                 ]
                     ] 



[#b
     [ 
       [7  2  3]
       [1  2  9]
       [1  2  3]
       [8  0  3]
       [1  7  3]
                 ]
     [ 
       [3  9  0]
       [2  2  3]
       [8  1  3]
       [0  2  3]
                 ],
     [ 
       [10   0  3]
       [0  NaN  9]
       [10 NaN  3]
                 ],
     [ 
       [0  2  NaN]
       [1  Nan  3]
                 ],
     [ 
       [1  2  NaN]
                 ],
     [           
                 ]
                     ] 

a = [    [                ],
     [ [1, 2, 3]          ],
     [ [0, 2, 7],  [1,np.nan,3]   ],
     [ 
       [10,0,3],  [np.nan,9,9],  [10,np.nan,3]
                 ],
     [ 
       [8,2,0],  [2,2,3],  [8,1,3],  [1,2,3]
                 ],
     [   
      [0,2,3],  [1,2,9],  [1,2,3],  [1,0,3],     [1,2,3]    
                 ]
                     ] 
 
b = [
     [ 
       [7,2,3],     [1,2,9],   [1,2,3],  [8,0,3],   [1,7,3]
                   ],
     [ 
       [3,9,0],   [2,2,3],   [8,1,3],   [0,2,3]
                   ],
     [ 
       [10,0,3],  [0,np.nan,9],   [10,np.nan,3]
                   ],
     [ 
       [0,2,np.nan],  [1,np.nan,3]
                   ],
     [ 
       [1,2,np.nan]
                   ],
     [           
                   ]
                     ]

risultato previsto:

[ 
     [ [7  2  3]# from b
       [1  2  9]# from b
       [1  2  3]# from b
       [8  0  3]# from b
       [1  7  3]# from b
                  ],
     [ 
       [1  2  3]
       [3  9  0]# from b
       [2  2  3]# from b
       [8  1  3]# from b
       [0  2  3]# from b
                 ],
     [ 
       [0  2    7]
       [1  Nan  3]
       [10   0  3]# from b
       [0  NaN  9]# from b
       [10 NaN  3]# from b
                 ],
     [ 
       [10   0  3]
       [NaN  9  9]
       [10 NaN  3]
       [0  2  NaN]# from b
       [1  Nan  3]# from b
                    ],
     [ 
       [8  2  0]
       [2  2  3]
       [8  1  3]
       [1  2  3]
       [1  2  NaN]# from b
                 ],
     [ 
       [0  2  3]
       [1  2  9]
       [1  2  3]
       [1  0  3]
       [1  2  3]
                 ] 
                     ] 

Conosci un modo per farlo in modo efficiente?

EDIT: provato a concatenare (non ha funzionato):

DF_LEN, COL_LEN, cols = 20,5,['A', 'B']
a = np.asarray(pd.DataFrame(1, index=range(DF_LEN), columns=cols))
a = list((map(lambda i: a[:i], range(1,a.shape[0]+1))))
  
b = np.asarray(pd.DataFrame(np.nan, index=range(DF_LEN), columns=cols))
b = list((map(lambda i: b[:i], range(1,b.shape[0]+1))))
b = b[::-1]

a_first = a[0];  del a[0]
b_last  = b[-1]; del b[-1]
result  = np.concatenate([a, b], axis=1)

>>>AxisError: axis 1 is out of bounds for array of dimension 1

Risposte

2 CrazyCoder Aug 27 2020 at 19:41

Non è possibile avere un array con lunghezza variabile in una dimensione. ae bsono molto probabilmente elenchi di elenchi e non array. Puoi usare la comprensione dell'elenco insieme a zip:

np.array([x+y for x,y in zip(a,b)]) 

EDIT : o in base al commento fornito se ae bsono elenchi di array:

np.array([np.vstack((x,y)) for x,y in zip(a,b)])

L'output del tuo esempio è simile a:

[[[ 7.  2.  3.]
  [ 1.  2.  9.]
  [ 1.  2.  3.]
  [ 8.  0.  3.]
  [ 1.  7.  3.]]

 [[ 1.  2.  3.]
  [ 3.  9.  0.]
  [ 2.  2.  3.]
  [ 8.  1.  3.]
  [ 0.  2.  3.]]

 [[ 0.  2.  7.]
  [ 1. nan  3.]
  [10.  0.  3.]
  [ 0. nan  9.]
  [10. nan  3.]]

 [[10.  0.  3.]
  [nan  9.  9.]
  [10. nan  3.]
  [ 0.  2. nan]
  [ 1. nan  3.]]

 [[ 8.  2.  0.]
  [ 2.  2.  3.]
  [ 8.  1.  3.]
  [ 1.  2.  3.]
  [ 1.  2. nan]]

 [[ 0.  2.  3.]
  [ 1.  2.  9.]
  [ 1.  2.  3.]
  [ 1.  0.  3.]
  [ 1.  2.  3.]]]
1 Valdi_Bo Aug 27 2020 at 19:15

Per eseguire la tua concatenazione, esegui:

result = np.concatenate([a, b], axis=1)

Per provare questo codice, ho creato una e B come:

a = np.stack([ np.full((2, 3), i) for i in range(1, 6)], axis=1)
b = np.stack([ np.full((2, 3), i + 10) for i in range(1, 4)], axis=1)

Quindi contengono:

array([[[1, 1, 1],        array([[[11, 11, 11],
        [2, 2, 2],                [12, 12, 12],
        [3, 3, 3],                [13, 13, 13]],
        [4, 4, 4],        
        [5, 5, 5]],              [[11, 11, 11],
                                  [12, 12, 12],
       [[1, 1, 1],                [13, 13, 13]]])
        [2, 2, 2],
        [3, 3, 3],
        [4, 4, 4],
        [5, 5, 5]]])

e le loro forme sono: (2, 5, 3) e (2, 3, 3)

Il risultato della mia concatenazione è:

array([[[ 1,  1,  1],
        [ 2,  2,  2],
        [ 3,  3,  3],
        [ 4,  4,  4],
        [ 5,  5,  5],
        [11, 11, 11],
        [12, 12, 12],
        [13, 13, 13]],

       [[ 1,  1,  1],
        [ 2,  2,  2],
        [ 3,  3,  3],
        [ 4,  4,  4],
        [ 5,  5,  5],
        [11, 11, 11],
        [12, 12, 12],
        [13, 13, 13]]])

e la forma è (2, 8, 3) , proprio come dovrebbe essere.

Modifica seguendo il commento a partire da 19: 56Z

Ho provato il codice dal tuo commento. Dopo aver eseguito a = list((map(lambda i: a[:i], range(1,a.shape[0]+1)))), il risultato è:

[array([[1, 1]], dtype=int64),
 array([[1, 1],
        [1, 1]], dtype=int64),
 array([[1, 1],
        [1, 1],
        [1, 1]], dtype=int64),
 array([[1, 1],
        [1, 1],
        [1, 1],
        [1, 1]], dtype=int64),
 array([[1, 1],
        [1, 1],
        [1, 1],
        [1, 1],
        [1, 1]], dtype=int64),
...

quindi a è un elenco di array di dimensioni variabili.

C'è qualcosa di sbagliato nel modo in cui costruisci i tuoi dati. Per prima cosa controlla che entrambi gli array siano tridimensionali e le loro forme differiscano solo nell'asse 1. Solo allora puoi eseguire il mio codice su di essi. Per ora sia a che b sono semplici elenchi pitonici , non array Numpy !