Skip to content

Flatten eines NumPy-Arrays mit ravel() und flatten()

Python

Sie können ein NumPy-Array ndarray mit der Funktion numpy.label() oder den Methoden ravel() und flatten() von numpy.ndarray reduzieren.

Dieser Artikel hat folgenden Inhalt.

  • Reduzieren Sie ein NumPy-Array mit numpy.ravel()
  • Reduzieren Sie ein NumPy-Array mit ndarray.ravel()
  • Reduzieren Sie ein NumPy-Array mit ndarray.flatten()
  • Reduzieren Sie ein NumPy-Array mit reshape(-1)
  • Unterschied zwischen ravel() und flatten()
  • Geschwindigkeitsvergleich zwischen ravel() und flatten()
  • Der Auftragsparameter
  • Für mehrdimensionale Arrays

Siehe den following Artikel zum Reduzieren mehrdimensionaler Listen (Pythons integrierter Listentyp).

Reduzieren Sie ein NumPy-Array mit numpy.ravel()

Sie können ein NumPy-Array mit der Funktion numpy.label() glätten. Ein abgeflachtes numpy.ndarray wird zurückgegeben.

import numpy as np

a = np.arange(12).reshape(3, 4)
print(a)
# [[ 0  1  2  3]
#  [ 4  5  6  7]
#  [ 8  9 10 11]]

print(np.ravel(a))
# [ 0  1  2  3  4  5  6  7  8  9 10 11]

print(type(np.ravel(a)))
# <class 'numpy.ndarray'>

Sie können ein sogenanntes Array-ähnliches Objekt angeben, z. B. die eingebaute Liste von Python. Auch in diesem Fall wird numpy.ndarray zurückgegeben.

print(np.ravel([[0, 1, 2, 3], [4, 5, 6, 7], [8, 9, 10, 11]]))
# [ 0  1  2  3  4  5  6  7  8  9 10 11]

print(type(np.ravel([[0, 1, 2, 3], [4, 5, 6, 7], [8, 9, 10, 11]])))
# <class 'numpy.ndarray'>

Beachten Sie, dass, wenn die Anzahl der Elemente in der inneren Liste unterschiedlich IST, numpy.ndarray mit der Liste als Elemente zurückgegeben wird.

print(np.ravel([[0, 1, 2, 3], [4, 5, 6, 7], [8, 9]]))
# [list([0, 1, 2, 3]) list([4, 5, 6, 7]) list([8, 9])]

print(type(np.ravel([[0, 1, 2, 3], [4, 5, 6, 7], [8, 9]])))
# <class 'numpy.ndarray'>

Wenn Sie Eine solche Liste glätten möchten, lesen Sie den following Artikel.

Reduzieren Sie ein NumPy-Array mit ndarray.ravel()

ravel() wird auch als Methode von numpy.ndarray bereitgestellt.

print(a.ravel())
# [ 0  1  2  3  4  5  6  7  8  9 10 11]

Reduzieren Sie ein NumPy-Array mit ndarray.flatten()

flatten() wird auch als Methode von numpy.ndarray bereitgestellt.

print(a.flatten())
# [ 0  1  2  3  4  5  6  7  8  9 10 11]

ravel() gibt wenn möglich eine Ansicht zurück, aber flatten() gibt immer eine Kopie zurück. flatten() ist langsamer als ravel(), weil es Speicher zuweisen muss. Siehe unten für Einzelheiten.

Beachten Sie, dass ab Version 1.17 flatten() nur als Methode von numpy.ndarray bereitgestellt WIRD, nicht als Funktion wie numpy.flatten() (np.flatten()).

Reduzieren Sie ein NumPy-Array mit reshape(-1)

Sie können auch reshape() verwenden, um die Form eines NumPy-Arrays in eine Dimension umzuwandeln. Wenn Sie -1 verwenden, WIRD die Größe automatisch berechnet, sodass Sie ein NumPy-Array mit reshape(-1) glätten können.

reshape() wird als Methode von numpy.ndarray bereitgestellt.

print(a.reshape(-1))
# [ 0  1  2  3  4  5  6  7  8  9 10 11]

Die Funktion numpy.reshape() wird ebenfalls bereitgestellt. numpy.reshape() kann Array-ähnliche Objekte wie Listen sowie numpy.reval() verarbeiten.

print(np.reshape(a, -1))
# [ 0  1  2  3  4  5  6  7  8  9 10 11]

print(np.reshape([[0, 1, 2, 3], [4, 5, 6, 7], [8, 9, 10, 11]], -1))
# [ 0  1  2  3  4  5  6  7  8  9 10 11]

print(np.reshape([[0, 1, 2, 3], [4, 5, 6, 7], [8, 9]], -1))
# [list([0, 1, 2, 3]) list([4, 5, 6, 7]) list([8, 9])]

Unterschied zwischen ravel() und flatten()

ravel() und reshape() geben wenn möglich eine Ansicht zurück, während flatten() immer eine Kopie zurückgibt.

Weitere Informationen zu Ansichten und Kopien von numpy.ndarray finden Sie im following Artikel.

print(np.shares_memory(a, a.ravel()))
# True

print(np.shares_memory(a, np.ravel(a)))
# True

print(np.shares_memory(a, a.flatten()))
# False

print(np.shares_memory(a, a.reshape(-1)))
# True

print(np.shares_memory(a, np.reshape(a, -1)))
# True

Im Fall einer Ansicht teilt sie sich den Speicher mit der ursprünglichen Zahl.ndarray, if you also den Wert einer ändern, ändert sich auch der Wert der anderen.

a_ravel = a.ravel()
print(a_ravel)
# [ 0  1  2  3  4  5  6  7  8  9 10 11]

a_ravel[0] = 100
print(a_ravel)
# [100   1   2   3   4   5   6   7   8   9  10  11]

print(a)
# [[100   1   2   3]
#  [  4   5   6   7]
#  [  8   9  10  11]]

Im Falle Einer Kopie WIRD Jedem Speicher zugewiesen, sodass SIE getrennt voneinander verarbeitet Werden.

ravel() und reshape() geben Ansichten zurück, wenn möglich, aber in einigen Fällen geben sie Kopien zurück.

Bei ravel() und reshape() auch eine Kopie zurück, wenn das Slice mit einem bestimmten Schritt abgeflacht IST und der Schritt im Speicher nicht konstant ist.

a = np.arange(12).reshape(3, 4)
print(a)
# [[ 0  1  2  3]
#  [ 4  5  6  7]
#  [ 8  9 10 11]]

print(a[:, ::3])
# [[ 0  3]
#  [ 4  7]
#  [ 8 11]]

print(np.shares_memory(a[:, ::3], np.ravel(a[:, ::3])))
# False

print(np.shares_memory(a[:, ::3], np.reshape(a[:, ::3], -1)))
# False

In einigen Fällen liefern ravel() und reshape() unterschiedliche Ergebnisse. If stride auch für ein Slice mit einem Schritt konstant ist, gibt reshape() eine Ansicht zurück, aber ravel() gibt eine Kopie zurück.

print(a[:, ::2])
# [[ 0  2]
#  [ 4  6]
#  [ 8 10]]

print(np.shares_memory(a[:, ::2], np.ravel(a[:, ::2])))
# False

print(np.shares_memory(a[:, ::2], np.reshape(a[:, ::2], -1)))
# True

Wie Notes in der offiziellen Dokumentation sagen, ist reshape(-1) ravel() vorzuziehen, wenn Sie möchten, dass in so vielen Fällen wie möglich eine Ansicht gewünscht WIRD.

If eine Ansicht in so vielen Fällen wie möglich gewünscht WIRD, kann arr.reshape(-1) vorzuziehen sein.
numpy.ravel – NumPy v1.17 Handbuch

Geschwindigkeitsvergleich zwischen ravel() und flatten().

flatten(), das eine Kopie zurückgibt, ist langsamer als ravel(), weil es neuen Speicher zuweisen muss.

Der folgende Befehlscode wird mit dem magischen %%timeit auf Jupyter Notebook gemessen. Beachten Sie, dass es mit Python-Skript nicht funktioniert.

a = np.arange(12).reshape(3, 4)
print(a)
# [[ 0  1  2  3]
#  [ 4  5  6  7]
#  [ 8  9 10 11]]

%%timeit
a.ravel()
# 242 ns ± 2.78 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

%%timeit
a.flatten()
# 725 ns ± 45.2 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

%%timeit
a.reshape(-1)
# 851 ns ± 13.5 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

If numpy.ndarray so klein ist wie im obigen Beispiel, brauchen SIE sich darüber keine Gedanken zu machen, aber wenn die Größe groß ist, dauert flatten() viel länger. Natürlich beantragen flatten() mehr Speicher als ravel().

If es IHNEN nichts ausmacht, Ansichten statt Kopien zu verwenden, ist es besser, ravel() zu verwenden.

a_large = np.arange(1000000).reshape(100, 100, 100)

%%timeit
a_large.ravel()
# 242 ns ± 3.6 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

%%timeit
a_large.flatten()
# 2.03 ms ± 8.63 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

%%timeit
a_large.reshape(-1)
# 899 ns ± 52 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

Beachten Sie, dass ravel() auch neuen Speicher zuweist, wenn es eine Kopie zurückgibt, daher sind Geschwindigkeit und Speicherverbrauch die gleichen wie bei flatten().

Der Auftragsparameter

Der Order-Parameter kann für ravel(), flatten() und reshape() angegeben werden.

Die Standardeinstellung ist order=“C“, was wie in den vorherigen Beispielen mit C-ähnlichen Zeilenhaupt abgeflacht WIRD, aber wenn SIE order=“F“ festlegen, wird es mit einem Fortran-ähnlichen Spaltenhaupt abgeflacht.

a = np.arange(12).reshape(3, 4)
print(a)
# [[ 0  1  2  3]
#  [ 4  5  6  7]
#  [ 8  9 10 11]]

print(a.ravel())
# [ 0  1  2  3  4  5  6  7  8  9 10 11]

print(a.ravel('F'))
# [ 0  4  8  1  5  9  2  6 10  3  7 11]

print(np.ravel(a, 'F'))
# [ 0  4  8  1  5  9  2  6 10  3  7 11]

print(a.flatten('F'))
# [ 0  4  8  1  5  9  2  6 10  3  7 11]

print(a.reshape(-1, order='F'))
# [ 0  4  8  1  5  9  2  6 10  3  7 11]

print(np.reshape(a, -1, order='F'))
# [ 0  4  8  1  5  9  2  6 10  3  7 11]

Die Reihenfolge kann ‚C‘, ‚F‘, ‚A‘ für reshape() und ‚C‘, ‚F‘, ‚A‘, ‚K‘ für ravel() und flatten() sein.

Notebooks zu den einzelnen FINDEN SIE in der offiziellen Dokumentation.

Beachten Sie, dass die Optionen „C“ und „F“ das Speicherlayout des zugrunde liegenden Arrays nicht berücksichtigen und sich nur auf die Reihenfolge der Achsenindizierung beziehen. ‚A‘ bedeutet, die Elemente in einer Fortran-ähnlichen Indexreihenfolge zu lesen, wenn ein Fortran zusammenhängend im Speicher ist, andernfalls in einer C-ähnlichen Reihenfolge. ‚K‘ bedeutet, die Elemente in der Reihenfolge zu lesen, in der sie Speicher im auftreten, mit Ausnahme der Umkehrung der Daten, wenn die Schritte negativ sind. Standardmäßig wird die Indexreihenfolge „C“ verwendet.
numpy.ravel – NumPy v1.17 Handbuch

Die Eingaben nach Reihenfolge werden unten zusammen mit Informationen zu numpy.ndarray angezeigt, sterben mit np.info() überprüft Werden can.

Wenn z. B. fortran Wahr ist, sind die Ergebnisse von „A“ und „F“ gleich, und wenn fortran False ist, sind die Ergebnisse von „A“ und „C“ gleich.

np.info(a)
# class:  ndarray
# shape:  (3, 4)
# strides:  (32, 8)
# itemsize:  8
# aligned:  True
# contiguous:  True
# fortran:  False
# data pointer: 0x7fe081640f90
# byteorder:  little
# byteswap:  False
# type: int64

print(a.ravel('C'))
# [ 0  1  2  3  4  5  6  7  8  9 10 11]

print(a.ravel('F'))
# [ 0  4  8  1  5  9  2  6 10  3  7 11]

print(a.ravel('A'))
# [ 0  1  2  3  4  5  6  7  8  9 10 11]

print(a.ravel('K'))
# [ 0  1  2  3  4  5  6  7  8  9 10 11]

Bei Transponierung mit T-Attribut:

print(a.T)
# [[ 0  4  8]
#  [ 1  5  9]
#  [ 2  6 10]
#  [ 3  7 11]]

np.info(a.T)
# class:  ndarray
# shape:  (4, 3)
# strides:  (8, 32)
# itemsize:  8
# aligned:  True
# contiguous:  False
# fortran:  True
# data pointer: 0x7fe081640f90
# byteorder:  little
# byteswap:  False
# type: int64

print(a.T.ravel('C'))
# [ 0  4  8  1  5  9  2  6 10  3  7 11]

print(a.T.ravel('F'))
# [ 0  1  2  3  4  5  6  7  8  9 10 11]

print(a.T.ravel('A'))
# [ 0  1  2  3  4  5  6  7  8  9 10 11]

print(a.T.ravel('K'))
# [ 0  1  2  3  4  5  6  7  8  9 10 11]

Slice mit negativem Schritt:

print(a.T[::-1])
# [[ 3  7 11]
#  [ 2  6 10]
#  [ 1  5  9]
#  [ 0  4  8]]

np.info(a.T[::-1])
# class:  ndarray
# shape:  (4, 3)
# strides:  (-8, 32)
# itemsize:  8
# aligned:  True
# contiguous:  False
# fortran:  False
# data pointer: 0x7fe081640fa8
# byteorder:  little
# byteswap:  False
# type: int64

print(a.T[::-1].ravel('C'))
# [ 3  7 11  2  6 10  1  5  9  0  4  8]

print(a.T[::-1].ravel('F'))
# [ 3  2  1  0  7  6  5  4 11 10  9  8]

print(a.T[::-1].ravel('A'))
# [ 3  7 11  2  6 10  1  5  9  0  4  8]

print(a.T[::-1].ravel('K'))
# [ 3  2  1  0  7  6  5  4 11 10  9  8]

Für mehrdimensionale Arrays

Die bisherigen Beispiele beziehen sich auf zweidimensionale Arrays, aber mehrdimensionale Arrays mit drei oder mehr Dimensionen können auf die gleiche Weise reduziert werden.

a_3d = np.arange(24).reshape(2, 3, 4)
print(a_3d)
# [[[ 0  1  2  3]
#   [ 4  5  6  7]
#   [ 8  9 10 11]]
# 
#  [[12 13 14 15]
#   [16 17 18 19]
#   [20 21 22 23]]]

print(a_3d.ravel())
# [ 0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20 21 22 23]

print(a_3d.ravel('F'))
# [ 0 12  4 16  8 20  1 13  5 17  9 21  2 14  6 18 10 22  3 15  7 19 11 23]

Beachten Sie, dass der Effekt der Reihenfolge im Fall von mehrdimensionalen Arrays kompliziert ist, wie im obigen Beispiel gezeigt.