Von ND zu 1D Arrays

141

Angenommen, ich habe ein Array a:

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

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

Ich möchte es in ein 1D-Array (dh einen Spaltenvektor) konvertieren:

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

aber das kehrt zurück

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

Das ist nicht dasselbe wie:

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

Ich kann das erste Element dieses Arrays verwenden, um es manuell in ein 1D-Array zu konvertieren:

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

Dazu muss ich jedoch wissen, wie viele Dimensionen das ursprüngliche Array hat (und [0] verketten, wenn ich mit höheren Dimensionen arbeite).

Gibt es eine dimensionsunabhängige Möglichkeit, einen Spalten- / Zeilenvektor von einem beliebigen ndarray abzurufen?

Amelio Vazquez-Reina
quelle

Antworten:

277

Verwenden Sie np.ravel (für eine 1D-Ansicht) oder np.ndarray.flatten (für eine 1D-Kopie) oder np.ndarray.flat (für einen 1D-Iterator):

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])

Beachten Sie, dass ravel()nach Möglichkeit ein viewvon zurückgegeben wird a. Das Ändern bändert sich also auch a. ravel()Gibt a zurück, viewwenn die 1D-Elemente im Speicher zusammenhängend sind, würde aber a zurückgeben, copywenn beispielsweise ein aanderes Array mit einer Nicht-Einheitsschrittgröße (z a = x[::2]. B. ) geschnitten wurde .

Wenn Sie eine Kopie anstelle einer Ansicht wünschen, verwenden Sie

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

Wenn Sie nur einen Iterator möchten, verwenden Sie 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]
unutbu
quelle
4
<pedantic> Gibt in diesem Beispiel ravel()eine Ansicht zurück, dies ist jedoch nicht immer der Fall. Es gibt Fälle, in denen ravel()eine Kopie zurückgegeben wird. </ Pedantic>
Warren Weckesser
3
a.ravel()sieht ungefähr dreimal so schnell aus wie a.reshape(-1). a.flatten()ist viel langsamer, da es eine Kopie machen muss.
BallpointBen
25
In [14]: b = np.reshape(a, (np.product(a.shape),))

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

oder einfach:

In [16]: a.flatten()
Out[16]: array([1, 2, 3, 4, 5, 6])
NPE
quelle
11
Kann verwendet b = a.reshape(-1)kurz in erstem Beispiel.
Syrtis Major
5

Eine der einfachsten Möglichkeiten ist die Verwendung flatten()wie in diesem Beispiel:

 import numpy as np

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

Mein Array war so:

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

Nach der Verwendung flatten():

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

Es ist auch die Lösung von Fehlern dieser Art:

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

Für eine Liste von Arrays mit unterschiedlicher Größe verwenden Sie Folgendes:

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)

Ausgabe:

[1 2 3 4 5 6 7 8]

Bikram
quelle
Wie würden Sie die Form des aRückens bekommen b?
dvdblk
Wenn Sie 1D in Stücke teilen möchten. Siehe diese stackoverflow.com/a/8495740/6117565
Bikram
4

Ich wollte ein Benchmark-Ergebnis von Funktionen sehen, die in Antworten erwähnt wurden, einschließlich Unutbu's .

Ich möchte auch darauf hinweisen, dass numpy doc die Verwendung empfiehlt, arr.reshape(-1)falls die Ansicht vorzuziehen ist. (obwohl raveles im folgenden Ergebnis etwas schneller ist)


TL; DR : np.ravelist am leistungsfähigsten (in sehr geringem Umfang).

Benchmark

Funktionen:

numpy version: '1.18.0'

Ausführungszeiten auf verschiedenen ndarrayGrößen

+-------------+----------+-----------+-----------+-------------+
|  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 |
+-------------+----------+-----------+-----------+-------------+

Fazit

ravelund reshape(-1)'s Ausführungszeit war konsistent und unabhängig von der ndarray-Größe. Allerdings ravelist bisschen schneller, aber reshapebietet Flexibilität Größe bei der Neugestaltung. (Vielleicht empfiehlt numpy doc deshalb , es stattdessen zu verwenden. Oder es kann Fälle geben, in denen reshapedie Ansicht zurückgegeben wird und ravelnicht).
Wenn Sie mit einem großen ndarray arbeiten, flattenkann die Verwendung ein Leistungsproblem verursachen. Es wird empfohlen, es nicht zu verwenden. Es sei denn, Sie benötigen eine Kopie der Daten, um etwas anderes zu tun.

Verwendeter Code

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)
Haku
quelle
0

Obwohl dies nicht das np-Array-Format verwendet (zu faul, um meinen Code zu ändern), sollte dies tun, was Sie wollen ... Wenn Sie wirklich einen Spaltenvektor wollen, möchten Sie das Vektorergebnis transponieren. Es hängt alles davon ab, wie Sie dies verwenden möchten.

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]

Wenn Sie also transponieren müssen, können Sie Folgendes tun:

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
xcellsior
quelle