Nächstes Kapitel: Python, Numpy, Wahrschein-lichkeit und Wahrscheinlich-keits-Rechnung
# invisible
import numpy as np
np.core.arrayprint._line_width = 65
Bisher lernten wir, wie man Arrays erzeugt und wie wir numerische Operationen auf NumPy Arrays anwenden können. Wenn wir mit NumPy programmieren, kommen wir früher oder später zu dem Punkt, wo wir Funktionen benötigen, um die Gestalt (shape) und die Dimension von Arrays zu manipulieren. Die dazu nötigen Funktionalitäten lernen wir in diesem Kapitel kennen. Wir werden auch lernen, wie man Arrays zusammenhängt bzw. konkateniert. Weiterhin werden wir die Möglichkeiten demonstrieren, wie man weitere Dimensionen an existierende Arrays anhängen kann und wie man mehrere Arrays horizontal und vertikal "stapeln" (stack) kann. Dieses Kapitel beenden wir, indem wir zeigen, wie man neue Arrays durch Wiederholungen aus existierenden Arrays erzeugen kann.
Das Bild zeigt einen Tesserakt, den man auch als vierdimensionalen Hyperwürfel bezeichnet. Ein Tesserakt kann man als die Übertragung des Konzeptes eines dreimensionalen Würfels in den vierdimensionalen Raum sehen. Ein Tesserakt verhält sich zum Würfel wie ein Würfel zum Quadrat.
Reduktion und Reshape von Arrays
Es gibt mehrere Methoden, um ein multidimensionales Array zu reduzieren:
flatten
ravel
reshape
flatten
ist eine ndarray-Methode mit einem optionalen Parameter order
, der die Werte C
, F
und A
annehmen kann.
Der Default-Wert von order
ist C
.
C
steht dafür, dass im C-Stil in der Zeilen-Haupt-Ordnung linearisiert bzw. flach gemacht wird, d.h. der am weitesten rechts liegende Index "ändert sich am schnellsten". In anderen Worten: Der Zeilenindex variiert in der Zeilen-Haupt-Ordnung am langsamsten und am Spaltenindex am schnellsten, sodass a[0, 1]
auf a[0, 0]
folgt.
F
steht für "Fortran Spalten-Haupt-Ordnung".
A
steht für den Erhalt der "C/Fortran-Anordnung".
import numpy as np
A = np.array([[[ 0, 1],
[ 2, 3],
[ 4, 5],
[ 6, 7]],
[[ 8, 9],
[10, 11],
[12, 13],
[14, 15]],
[[16, 17],
[18, 19],
[20, 21],
[22, 23]]])
Flattened_X = A.flatten()
print(Flattened_X)
print(A.flatten(order="C"))
print(A.flatten(order="F"))
print(A.flatten(order="A"))
Die Reihenfolge der Elemente, die durch ravel() zurückgeliefert wird, ist standardmäßig im "C-Stil".
ravel(X, order='C')
ravel
erzeugt ein linearisiertes, also eindimensionales, Array .
Eine Kopie wird nur bei Notwendigkeit erstellt.
Der optionale Parameter order
kann die Werte C
, F
, A
oder K
annehmen.
C
: C-Stil Reihenfolge, wobei sich der letzte Achsenindex am schnellsten ändert, zurück zum ersten Achsenindex, der sich am langsamsten ändert.
C
ist der Default-Wert.
F
: Fortran-Stil Indexreihenfolge, wobei sich der erste Index am schnellsten ändert und der letzte Index am langsamsten.
A
: Fortran-Stil Indexreihenfolge, wenn das Array 'a' im Speicher als Fortran vorliegt, andernfalls wird die C-Stil Reihenfolge verwendet.
K
: Die Elemente werden so gelesen, wie sie im Speicher vorkommen, außer für Datenumkehrung, wenn die Schrittweiten negativ sind.
print(A.ravel())
print(A.ravel(order="A"))
print(A.ravel(order="F"))
print(A.ravel(order="A"))
print(A.ravel(order="K"))
import numpy as np
A = np.array([[1, 2, 3],
[4, 5, 6]])
B = A.flatten()
B[4] = 42
print("B: \n", B)
print("A: \n", A)
print(np.may_share_memory(A, B))
print("\n... und jetzt das Ganze mit ravel:")
B = A.ravel()
B[4] = 42
print("B: \n", B)
print("A: \n", A)
print(np.may_share_memory(A, B))
Die reshape
-Methode wandelt ein Array in eine neue Gestalt, englisch ,,Shape'', ohne die darin enthaltenen Daten zu ändern, d.h. die eigentlichen Daten müssen nicht kopiert werden.
reshape(a, newshape, order='C')
Parameter | Bedeutung |
---|---|
a | array-ähnlich, Array, das geändert werden soll. |
newshape | Integer-Wert oder Integer-Tupel |
order | 'C', 'F', 'A', wie in flatten() oder ravel() |
Mittels reshape
können wir ein Array auch linearisieren:
A = np.array([[1, 2, 3],
[4, 5, 6]])
B = A.reshape((6,))
print(B)
Damit kann reshape
die Aufgaben von ravel
und flatten
übernehmen. reshape
kann aber noch mehr. Wir können damit ein Array A in eine beliebige Gestalt x
überführen, solange das Produkt der Shape-Komponenten von A gleich dem Produkt der Shape-Komponenten von x
ist, also
np.prod(A.shape) == np.prod(x)
X = np.array(range(24))
Y1 = X.reshape((3, 4, 2))
print(Y1)
new_shape = (2, 3, 4)
Y2 = Y1.reshape(new_shape)
print(Y2)
Es gilt:
np.prod(Y1.shape) == np.prod(new_shape)
Im folgenden Beispiel konkatenieren wir drei eindimensionale Arrays zu einem. Die Elemente des zweiten Arrays werden an das erste Array horizontal angefügt. Anschließend werden die Elemente des dritten Arrays ebenfalls horizontal angefügt:
x = np.array([11, 22])
y = np.array([18, 7, 6])
z = np.array([1, 3, 5])
c = np.concatenate((x, y, z))
print(c)
Wenn wir multidimensionale Arrays zusammenführen, müssen wir auf die Achsen achten.
Die Arrays müssen die gleiche Shape haben, um mit concatenate
zusammen gefügt werden zu können.
Bei multidimensionalen Arrays können wir diese entsprechend anordnen. Der Default-Wert ist axis = 0
:
x = np.array(range(12))
x = x.reshape((3, 4))
y = np.array(range(100, 112))
y = y.reshape((3, 4))
z = np.concatenate((x, y))
print(z)
Wir führen die Zusammenführung nun mit axis = 1
durch:
z = np.concatenate((x, y), axis=1)
print(z)
Weitere Dimensionen können zu einem Array mit Hilfe von Slicing und np.newaxis
hinzugefügt werden.
Wir demonstrieren die Technik im folgenden Beispiel:
x = np.array([2,5,18,14,4])
y = x[:, np.newaxis]
print(y)
Das gleiche Resultat lässt sich auch mit reshape
bewerkstelligen:
x = np.array([2,5,18,14,4])
y = x.reshape( (x.shape[0], 1) )
print(y)
A = np.array([[3, 4, 5]])
B = np.array([[1,9,0]])
C = np.dstack((A, B))
print("Elemente von A:")
for i in range(C.shape[1]):
print(C[0, i, 0], end=", ")
print("\nElemente von B:")
for i in range(C.shape[1]):
print(C[0, i, 1], end=", ")
Wir können sehen, dass wir den i-ten Eingabevektor von C erhalten, indem wir den Ausdruck C[:, :, i]
ausführen:
print("Erster Eingabevektor, d.h. A:", C[:, :, 0])
print("Zweiter Eingabevektor, d.h. B:", C[:, :, 1])
Als Nächstes betrachten wir die Methoden row_stack
und column_stack
:
A = np.array([3, 4, 5])
B = np.array([1,9,0])
print(np.row_stack((A, B)))
print(np.column_stack((A, B)))
print(np.shape(A))
A = np.array([[1, 2],
[3, 4]])
X = np.column_stack((A, A, A))
print(np.row_stack((X, X, X)))
"Fliesen" mit "tile"
Manchmal ist es nötig, eine Matrix zu erstellen (mit einer anderen Shape oder Dimension), die den Inhalt einer existierenden Matrix mehrfach enthält.
Beispiel:
Man möchte das eindimensionale Array array([ 3.4])
in das Array array([ 3.4, 3.4, 3.4, 3.4, 3.4])
wandeln.
Weiteres Beispiel:
Man möchte ein zweidimensionales Array, wie np.array([ [1, 2], [3, 4]])
, als Baustein benutzen, um ein Array mit der Shape (6, 8) zu erstellen:
array([[1, 2, 1, 2, 1, 2, 1, 2], [3, 4, 3, 4, 3, 4, 3, 4], [1, 2, 1, 2, 1, 2, 1, 2], [3, 4, 3, 4, 3, 4, 3, 4], [1, 2, 1, 2, 1, 2, 1, 2], [3, 4, 3, 4, 3, 4, 3, 4]])
Die Konstruktionsidee ist im folgenden Diagramm dargestellt:
import numpy as np
x = np.array([ [1, 2], [3, 4]])
print(np.tile(x, (3, 4)))
import numpy as np
x = np.array([ 3.4])
y = np.tile(x, (5,))
print(y)
Im vorigen tile
-Beispiel hätten wir ebenso y = np.tile(x, 5)
schreiben können.
Wenn wir reps
in Tupel- oder List-Form schreiben, oder reps = 5
als Ersatz für reps = (5,)
in Erwägung ziehen, so ist Folgendes wahr:
Wenn reps
die Länge n
hat, so wird die Dimension des resultierenden Arrays maximal n
und A.ndim
sein.
Wenn A.ndim < n
ist, so wird A
durch Voranstellen neuer Achsen auf die n-Dimensionen befördert.
Beispielsweise wird ein Array mit der Shape (5,)
auf (1, 5)
bei einer 2-D-Replikation befördert oder auf die Shape (1, 1, 5)
bei einer 3-D-Replikation.
Sollte das nicht dem gewünschten Verhalten entsprechen, so ist A
vor dem Aufruf der tile-Funktion auf die gewünschte Shape anzupassen.
Wenn A.ndim > d
ist, so wird reps
auf A.ndim
angepasst, indem 1's vorangestellt werden.
Beispielsweise wird ein Array A
mit der Shape (2, 3, 4, 5)
und reps = (2, 2)
als (1, 1, 2, 2)
behandelt.
Weitere Beispiele:
import numpy as np
x = np.array([[1, 2], [3, 4]])
print(np.tile(x, 2))
import numpy as np
x = np.array([[1, 2], [3, 4]])
print(np.tile(x, (2, 1)))
import numpy as np
x = np.array([[1, 2], [3, 4]])
print(np.tile(x, (2, 2)))
Nächstes Kapitel: Python, Numpy, Wahrschein-lichkeit und Wahrscheinlich-keits-Rechnung