Da array ND a 1D


141

Di 'che ho un array a:

a = np.array([[1,2,3], [4,5,6]])

array([[1, 2, 3],
       [4, 5, 6]])

Vorrei convertirlo in un array 1D (cioè un vettore di colonna):

b = np.reshape(a, (1,np.product(a.shape)))

ma questo ritorna

array([[1, 2, 3, 4, 5, 6]])

che non è lo stesso di:

array([1, 2, 3, 4, 5, 6])

Posso prendere il primo elemento di questo array per convertirlo manualmente in un array 1D:

b = np.reshape(a, (1,np.product(a.shape)))[0]

ma questo mi richiede di sapere quante dimensioni ha l'array originale (e concatenare [0] quando si lavora con dimensioni più alte)

Esiste un modo indipendente dalle dimensioni per ottenere un vettore colonna / riga da un ndarray arbitrario?

Risposte:


277

Utilizzare np.ravel (per una vista 1D) o np.ndarray.flatten (per una copia 1D) o np.ndarray.flat (per un iteratore 1D):

In [12]: a = np.array([[1,2,3], [4,5,6]])

In [13]: b = a.ravel()

In [14]: b
Out[14]: array([1, 2, 3, 4, 5, 6])

Si noti che ravel()restituisce un viewdi aquando possibile. Quindi banche la modifica modifica a. ravel()restituisce a viewquando gli elementi 1D sono contigui in memoria, ma restituisce a copyse, ad esempio, afossero stati creati tagliando un altro array utilizzando una dimensione di passo non unitaria (ad es a = x[::2].).

Se si desidera una copia anziché una vista, utilizzare

In [15]: c = a.flatten()

Se vuoi solo un iteratore, usa np.ndarray.flat:

In [20]: d = a.flat

In [21]: d
Out[21]: <numpy.flatiter object at 0x8ec2068>

In [22]: list(d)
Out[22]: [1, 2, 3, 4, 5, 6]

4
<pedantico> In questo esempio, ravel()restituisce una vista, ma ciò non è sempre vero. Ci sono casi in cui ravel()restituisce una copia. </pedantic>
Warren Weckesser il

3
a.ravel()sembra essere circa tre volte più veloce di a.reshape(-1). a.flatten()è molto più lento, in quanto deve fare una copia.
BallpointBen,

25
In [14]: b = np.reshape(a, (np.product(a.shape),))

In [15]: b
Out[15]: array([1, 2, 3, 4, 5, 6])

o semplicemente:

In [16]: a.flatten()
Out[16]: array([1, 2, 3, 4, 5, 6])

11
Può usare b = a.reshape(-1)in breve nel primo esempio.
Syrtis Major,

5

Uno dei modi più semplici è usare flatten(), come in questo esempio:

 import numpy as np

 batch_y =train_output.iloc[sample, :]
 batch_y = np.array(batch_y).flatten()

Il mio array era così:

    0
0   6
1   6
2   5
3   4
4   3
.
.
.

Dopo aver usato flatten():

array([6, 6, 5, ..., 5, 3, 6])

È anche la soluzione di errori di questo tipo:

Cannot feed value of shape (100, 1) for Tensor 'input/Y:0', which has shape '(?,)' 

4

Per un elenco di array con dimensioni diverse utilizzare quanto segue:

import numpy as np

# ND array list with different size
a = [[1],[2,3,4,5],[6,7,8]]

# stack them
b = np.hstack(a)

print(b)

Produzione:

[1 2 3 4 5 6 7 8]


come otterresti la forma della aschiena b?
dvdblk,

Se vuoi dividere 1D in grossi pezzi. Vedi questo stackoverflow.com/a/8495740/6117565
bikram

4

Volevo vedere un risultato di riferimento delle funzioni menzionate nelle risposte, tra cui unutbu .

Voglio anche sottolineare che è preferibile usare doc intorpiditoarr.reshape(-1) nel caso in cui la vista sia preferibile. (anche se ravelè un po 'più veloce nel seguente risultato)


TL; DR : np.ravelè il più performante (in quantità molto ridotta).

Prova delle prestazioni

funzioni:

versione numpy: '1.18.0'

Tempi di esecuzione su diverse ndarraydimensioni

+-------------+----------+-----------+-----------+-------------+
|  function   |   10x10  |  100x100  | 1000x1000 | 10000x10000 |
+-------------+----------+-----------+-----------+-------------+
| ravel       | 0.002073 |  0.002123 |  0.002153 |    0.002077 |
| reshape(-1) | 0.002612 |  0.002635 |  0.002674 |    0.002701 |
| flatten     | 0.000810 |  0.007467 |  0.587538 |  107.321913 |
| flat        | 0.000337 |  0.000255 |  0.000227 |    0.000216 |
+-------------+----------+-----------+-----------+-------------+

Conclusione

ravele reshape(-1)il tempo di esecuzione era coerente e indipendente dalle dimensioni di ndarray. Tuttavia, ravelè un po 'più veloce, ma reshapeoffre flessibilità nel rimodellare le dimensioni. (forse è per questo che doc intorpidito consiglia di usarlo invece. Oppure potrebbero esserci alcuni casi in cui i reshaperesi vengono visualizzati e ravelnon lo fanno).
Se hai a che fare con ndarray di grandi dimensioni, l'utilizzo flattenpuò causare un problema di prestazioni. Consiglio di non usarlo. A meno che tu non abbia bisogno di una copia dei dati per fare qualcos'altro.

Codice usato

import timeit
setup = '''
import numpy as np
nd = np.random.randint(10, size=(10, 10))
'''

timeit.timeit('nd = np.reshape(nd, -1)', setup=setup, number=1000)
timeit.timeit('nd = np.ravel(nd)', setup=setup, number=1000)
timeit.timeit('nd = nd.flatten()', setup=setup, number=1000)
timeit.timeit('nd.flat', setup=setup, number=1000)

0

Anche se questo non utilizza il formato array np, (per pigro per modificare il mio codice), questo dovrebbe fare quello che vuoi ... Se vuoi veramente un vettore di colonna, vorrai trasporre il risultato del vettore. Tutto dipende da come pensi di usarlo.

def getVector(data_array,col):
    vector = []
    imax = len(data_array)
    for i in range(imax):
        vector.append(data_array[i][col])
    return ( vector )
a = ([1,2,3], [4,5,6])
b = getVector(a,1)
print(b)

Out>[2,5]

Quindi, se devi trasporre, puoi fare qualcosa del genere:

def transposeArray(data_array):
    # need to test if this is a 1D array 
    # can't do a len(data_array[0]) if it's 1D
    two_d = True
    if isinstance(data_array[0], list):
        dimx = len(data_array[0])
    else:
        dimx = 1
        two_d = False
    dimy = len(data_array)
    # init output transposed array
    data_array_t = [[0 for row in range(dimx)] for col in range(dimy)]
    # fill output transposed array
    for i in range(dimx):
        for j in range(dimy):
            if two_d:
                data_array_t[j][i] = data_array[i][j]
            else:
                data_array_t[j][i] = data_array[j]
    return data_array_t
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.