Arrays in Numpy erzeugen



Array mit Transportmitteln

Wir haben bereits im vorigen Kapitel unseres Numpy-Tutorials gesehen, dass wir Numpy-Arrays aus Listen und Tupel generieren können. Nun wollen wir weitere Funktionen zum Erzeugen von Arrays einführen.

Numpy bietet Funktionen, um Intervalle mit Werten zu erzeugen, deren Abstände gleichmäßig verteilt sind. 'arange' benutzt einen gegebenen Abstandwert um innerhalb von gegebenen Intervallgrenzen entsprechende Werte zu generieren, während 'linspace' eine bestimmte Anzahl von Werten innerhalb gegebener Intervallgrenzen berechnet. Den Abstand berechnet 'linspace' automatisch.



Erzeugung äquidistanter Intervalle



arange

Die Syntax von arange:

arange([start,] stop[, step], [, dtype=None])

arange liefert gleichmäßig verteilte Werte innerhalb eines gegebenen Intervalles zurück. Die Werte werden innerhalb des halb-offenen Intervalles [start, stop) generiert. Wird diese Funktion mit Integerwerten benutzt, ist sie beinahe äquivalent zu der built-in Python-Funktion range. arange liefert jedoch ein ndarray zurück, während range einen Listen-Iterator zurückliefert. Falls der start-Parameter nicht übergeben wird, wird start auf 0 gesetzt. Das Ende des Intervalls wird durch den Parameter stop bestimmt. Üblicherweise wird das Intervall diesen Wert nicht beinhalten, außer in den Fällen, in denen step keine Ganzzahl ist und floating-point-Effekte die Länge des Ausgabearrays beeinflussen. Der Abstand zwischen zwei benachbarten Werten des Ausgabearrays kann mittels des optionalen Parameters step gesetzt werden. Der Default-Wert für step ist 1.

Falls ein Wert für step angegeben wird, kann der start-Parameter nicht mehr optional sein, d.h. er muss dann auch angegeben werden.

Der Type des Ausgabearrays kann mit dem Parameter dtype bestimmt werden. Wird er nicht angegeben, wird der Typ automatisch aus den übergebenen Eingabewerten ermittelt.

import numpy as np
a = np.arange(1, 7)
print(a)
# im Vergleich dazu nun range:
x = range(1, 7)
print(x)    # x ist ein Iterator
print(list(x))
# weitere arange-Beispiele:
x = np.arange(7.3)
print(x)
x = np.arange(0.5, 6.1, 0.8)
print(x)
x = np.arange(0.5, 6.1, 0.8, int)
print(x)
[1 2 3 4 5 6]
range(1, 7)
[1, 2, 3, 4, 5, 6]
[0. 1. 2. 3. 4. 5. 6. 7.]
[0.5 1.3 2.1 2.9 3.7 4.5 5.3]
[0 1 2 3 4 5 6]



linspace

Die Syntax von linspace:

linspace(start, stop, num=50, endpoint=True, retstep=False)

linspace liefert ein ndarray zurück, welches aus 'num' gleichmäßig verteilten Werten aus dem geschlossenen Interval ['start', 'stop'] oder dem halb-offenen Intervall ['start', 'stop') besteht. Ob ein geschlossenes oder ein halb-offenes Intervall zurückgeliefert wird, hängt vom Wert des Parameters 'endpoint' ab. 'stop' ist der letzte Wert des Intervalls, falls 'endpoint' nicht auf False gesetzt ist. Die Schrittweite ist unterschiedlich, je nachdem ob 'endpoint' True oder False ist.

import numpy as np
# 50 Werte (Defaut) zwischen 1 und 10:
print(np.linspace(1, 10))
# 7 Werte zwischen 1 und 10:
print(np.linspace(1, 10, 7))
# jetzt ohne Endpunkt:
print(np.linspace(1, 10, 7, endpoint=False))
[ 1.          1.18367347  1.36734694  1.55102041  1.73469388  1.91836735
  2.10204082  2.28571429  2.46938776  2.65306122  2.83673469  3.02040816
  3.20408163  3.3877551   3.57142857  3.75510204  3.93877551  4.12244898
  4.30612245  4.48979592  4.67346939  4.85714286  5.04081633  5.2244898
  5.40816327  5.59183673  5.7755102   5.95918367  6.14285714  6.32653061
  6.51020408  6.69387755  6.87755102  7.06122449  7.24489796  7.42857143
  7.6122449   7.79591837  7.97959184  8.16326531  8.34693878  8.53061224
  8.71428571  8.89795918  9.08163265  9.26530612  9.44897959  9.63265306
  9.81632653 10.        ]
[ 1.   2.5  4.   5.5  7.   8.5 10. ]
[1.         2.28571429 3.57142857 4.85714286 6.14285714 7.42857143
 8.71428571]

Bis jetzt haben wir einen interessanten Parameter nicht besprochen. Falls der Parameter 'retstep' gesetzt ist, wird die Funktion auch den Wert des Abstandes zwischen zwei benachbarten Werten des Ausgabearrays zurückliefern. Die Funktion liefert also ein Tupel ('samples', 'step') zurück:

import numpy as np
samples, spacing = np.linspace(1, 10, 
                               retstep=True)
print(spacing)
samples, spacing = np.linspace(1, 10, 5, 
                               endpoint=True, retstep=True)
print(samples, spacing)
samples, spacing = np.linspace(1, 10, 5, 
                               endpoint=False, retstep=True)
print(samples, spacing)
0.1836734693877551
[ 1.    3.25  5.5   7.75 10.  ] 2.25
[1.  2.8 4.6 6.4 8.2] 1.8



Nulldimensionale Arrays in Numpy

In NumPy kann man mehrdimensionale Arrays erzeugen. Skalare sind 0-dimensional. Im folgenden Beispiel erzeugen wir den Skalar 42. Wenden wir die ndim-Methode auf unseren Skalar an, erhalten wir die Dimension des Arrays. Wir können außerdem sehen, dass der Typ ein numpy.ndarray-Typ ist.

import numpy as np
x = np.array(42)
print("x: ", x)
print("Der Typ von x: ", type(x))
print("Die Dimension von x:", np.ndim(x))
x:  42
Der Typ von x:  <class 'numpy.ndarray'>
Die Dimension von x: 0

Eindimensionales Array

Wir haben bereits in unserem anfänglichen Beispiel ein eindimensionales Array - besser als Vektoren bekannt - gesehen. Was wir bis jetzt noch nicht erwähnt haben, aber was Sie sich sicherlich bereits gedacht haben, ist die Tatsache, dass die NumPy-Arrays Container sind, die nur einen Typ enthalten können, also beispielsweise nur Integers. Den homogenen Datentyp eines Arrays können wir mit dem Attribut "dtype" bestimmen, wie wir im folgenden Beispiel lernen können:

F = np.array([1, 1, 2, 3, 5, 8, 13, 21])
V = np.array([3.4, 6.9, 99.8, 12.8])
print("F: ", F)
print("V: ", V)
print("Typ von F: ", F.dtype)
print("Typ von V: ", V.dtype)
print("Dimension von F: ", np.ndim(F))
print("Dimension von V: ", np.ndim(V))
F:  [ 1  1  2  3  5  8 13 21]
V:  [ 3.4  6.9 99.8 12.8]
Typ von F:  int64
Typ von V:  float64
Dimension von F:  1
Dimension von V:  1



Zwei- und Mehrdimensionale Arrays

Natürlich sind die Arrays in NumPy nicht auf eine Dimension beschränkt. Sie können eine beliebige Dimension haben. Wir erzeugen sie, indem wir verschachtelte Listen (oder Tupel) an die array-Methode von NumPy übergeben:

A = np.array([ [3.4, 8.7, 9.9], 
               [1.1, -7.8, -0.7],
               [4.1, 12.3, 4.8]])
print(A)
print(A.ndim)
[[ 3.4  8.7  9.9]
 [ 1.1 -7.8 -0.7]
 [ 4.1 12.3  4.8]]
2

Dreidimensionale Arrays werden wir uns in einem späteren Kapitel genauer anschauen.



Shape / Größe eines Arrays

Die Funktion "shape" liefert die Größe ("shape") eines Arrays zurück. Die Shape wird durch ein Integer-Tupel definiert. Diese Zahlen bezeichnen die Längen der entsprechenden Array-Dimensionen. In anderen Worten: Die Shape eines Arrays ist ein Tupel mit der Anzahl der Elemente pro Achse (Dimension). In unserem Beispiel ist die Shape gleich (6, 3). Das bedeutet, das wir sechs Zeilen und drei Spalten haben.

x = np.array([ [67, 63, 87],
               [77, 69, 59],
               [85, 87, 99],
               [79, 72, 71],
               [63, 89, 93],
               [68, 92, 78]])
print(np.shape(x))
(6, 3)

Es gibt auch eine äquivalente Array-Property:

print(x.shape)
(6, 3)

Numerierung der Achsen

Die Shape eines Arrays sagt uns auch etwas über die Reihenfolge, in der die Indizes ausgeführt werden, d.h. zuerst die Zeilen, dann die Spalten und dann gegebenenfalls eine weitere Dimension oder weitere Dimensionen.

"shape" kann auch dazu genutzt werden die "Shape" eines Arrays zu ändern.

x.shape = (3, 6)
print(x)
[[67 63 87 77 69 59]
 [85 87 99 79 72 71]
 [63 89 93 68 92 78]]
x.shape = (2, 9)
print(x)
[[67 63 87 77 69 59 85 87 99]
 [79 72 71 63 89 93 68 92 78]]

Viele haben sicherlich bereits vermutet, dass die neue Shape der Anzahl der Elemente des Arrays entsprechen muss, d.h. die totale Größe des neuen Arrays muss die gleiche als die alte sein. Eine Ausnahme wird erhoben (raised), wenn dies nicht der Fall ist, wenn man also zum Beispiel

x.shape = (4, 4)

eingibt.

Die Shape eines Skalars ist ein leeres Tupel:

x = np.array(11)
print(np.shape(x))
()

Im Folgenden sehen wir die Shape eines dreidimensionalen Shapes:

B = np.array([ [[111, 112], [121, 122]],
               [[211, 212], [221, 222]],
               [[311, 312], [321, 322]] ])
print(B.shape)
(3, 2, 2)



Indizierung und Teilbereichsoperator

Der Zugriff oder die Zuweisung an die Elemente eines Arrays funktioniert ähnlich wie bei den sequentiellen Datentypen von Python, d.h. den Listen und Tupeln. Außerdem haben wir verschiedene Optionen zu indizieren. Dies macht das Indizieren in Numpy sehr mächtig und ähnlich zum Standardpython.

Einzelne Element zu indizieren funktioniert so, wie es die meisten wahrscheinlich erwarten:

F = np.array([1, 1, 2, 3, 5, 8, 13, 21])
# Ausgabe des ersten Elements von F
print(F[0])
# print the last element of F
print(F[-1])
B = np.array([ [[111, 112], [121, 122]],
               [[211, 212], [221, 222]],
               [[311, 312], [321, 322]] ])
print(B[0][1][0])
1
21
121

Mehrdimensionale Arrays indizieren:

A = np.array([ [3.4, 8.7, 9.9], 
               [1.1, -7.8, -0.7],
               [4.1, 12.3, 4.8]])
print(A[1][0])
1.1

Wir haben auf das Element in der zweiten Zeile, d.h. die Zeile mit dem Index 1, und der ersten Spalte (Index 0) zugegriffen. Auf dieses Element haben wir in der gleichen Art zugegriffen, wie wir mit einem Element in einer verschachtelten Python-Liste verfahren hätten.

Es gibt aber auch eine Alternative: Wir benutzen nur ein Klammernpaar und alle Indizes werden mit Kommas separiert:

print(A[1, 0])
1.1

Man muss sich aber der Tatsache bewusst sein, dass die zweite Art effizienter ist. Im ersten Fall erzeugen wir als Zwischenschritt ein Array A[1], in dem wir dann auf das Element mit dem Index 0 zugreifen. Dies entspricht in etwa dem Folgenden:

tmp = A[1]
print(tmp)
print(tmp[0])
[ 1.1 -7.8 -0.7]
1.1

Wir nehmen an, dass Sie bereits vertraut sind mit den Teilbereichsoperatoren (slicing) von den Listen und Tupeln.

Das englische Verb "to slice" bedeutet in Deutsch "schneiden" oder auch "in Scheiben schneiden". Letztere Bedeutung entspricht auch der Arbeitsweise des Teilbereichsoperators in Python und Numpy. Man schneidet sich gewissermaßen eine "Scheibe" aus einem sequentiellen Datentyp oder einem Array heraus.

Die Syntax in Numpy ist analog zu der von Standardpython im Falle von eindimensionalen Arrays. Allerdings können wir "Slicing" auch auf mehrdimensionale Arrays anwenden.

Die allgemeine Syntax für den eindimensionalen Fall lautet wie folgt:

[start:stop:step]

Wir demonstrieren die Arbeitsweise des Teilbereichsoperators an einigen Beispielen. Wir beginnen mit dem einfachsten Fall, also dem eindimensionalen Array:

S = np.array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
print(S[2:5])
print(S[:4])
print(S[6:])
print(S[:])
[2 3 4]
[0 1 2 3]
[6 7 8 9]
[0 1 2 3 4 5 6 7 8 9]

Die Anwendung des Teilbereichsoperators auf mehrdimensionale Arrays illustrieren wir in den folgenden Beispielen. Die Bereiche für jede Dimension werden durch Kommas getrennt:

A = np.array([
[11, 12, 13, 14, 15],
[21, 22, 23, 24, 25],
[31, 32, 33, 34, 35],
[41, 42, 43, 44, 45],
[51, 52, 53, 54, 55]])
print(A[:3, 2:])
[[13 14 15]
 [23 24 25]
 [33 34 35]]

Abbildung zum ersten Beispiel eines Teilbereichsoperators in Numpy

print(A[3:, :])
[[41 42 43 44 45]
 [51 52 53 54 55]]

Abbildung zum zweiten Beispiel eines Teilbereichsoperators in Numpy

print(A[:, 4:])
[[15]
 [25]
 [35]
 [45]
 [55]]

Abbildung zum dritten Beispiel eines Teilbereichsoperators in Numpy

Die folgenden beiden Beispiele benutzten auch noch den dritten Parameter "step". Die reshape-Funktion benutzen wir um ein eindimensionales Array in ein zweidimensionales zu wandeln. Wir werden reshape im folgenden Unterkapitel erklären:

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

Abbildung zum vierten Beispiel eines Teilbereichsoperators in Numpy

print(X[::, ::3])
[[ 0  3  6]
 [ 7 10 13]
 [14 17 20]
 [21 24 27]]

Abbildung zum fünften Beispiel eines Teilbereichsoperators in Numpy

Warnzeichen

Falls die Zahl der Objekte in dem Auswahltupel kleiner als die Dimension N ist, dann wird ":" für die weiteren nicht angegebenen Dimensionen angenommen:

A = np.array(
    [ [ [45, 12, 4], [45, 13, 5], [46, 12, 6] ], 
      [ [46, 14, 4], [45, 14, 5], [46, 11, 5] ], 
      [ [47, 13, 2], [48, 15, 5], [52, 15, 1] ] ])
A[1:3, 0:2]  # equivalent to A[1:3, 0:2, :]
Wir können die folgende Ausgabe erwarten, wenn wir den obigen Python-Code ausführen:
array([[[46, 14,  4],
        [45, 14,  5]],
       [[47, 13,  2],
        [48, 15,  5]]])

Achtung: Während der Teilbereichsoperator bei Listen und Tupel neue Objekte erzeugt, generiert er bei Numpy nur eine Sicht (englisch: "view") auf das Originalarray. Dadurch erhalten wir eine andere Möglichkeit das Array anzusprechen, oder besser einen Teil des Arrays. Daraus folgt, dass wenn wir etwas in einer Sicht verändern, wir auch das Originalarray verändern.

A = np.array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
S = A[2:6]
S[0] = 22
S[1] = 23
print(A)
[ 0  1 22 23  4  5  6  7  8  9]

Wenn wir das analog bei Listen tun, sehen wir, dass wir eine Kopie erhalten. Genaugenommen müssten wir sagen, eine flache Kopie. Den Unterschied zwischen flacher und tiefer Kopie haben wir in unserem Kapitel "Flaches und tiefes Kopieren" ausführlich erklärt.

lst = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
lst2 = lst[2:6]
lst2[0] = 22
lst2[1] = 23
print(lst)
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

Will man prüfen, ob zwei Arrays auf den gleichen Speicherbereich zugreifen, so kann man die Funktion "np.may_share_memory" benutzen:

np.may_share_memory(A, B)

Um zu entscheiden, ob sich zwei Arrays A und B Speicher teilen, werden die Speichergrenzen von A und B berechnet. Die Funktion liefert True zurück, falls sie überlappen und ansonsten False.

A = np.array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
B = A[2:5]
np.may_share_memory(A, B)
Führt man obigen Code aus, erhält man Folgendes:
True

Die Funktion kann allerdings falsch-positive Ergebnisse liefern, d.h. falls sie True zurückliefert könnten die Arrays dennoch verschieden sein.

Im folgenden Beispiel haben B1 und B2 keine gemeinsamen Daten, aber die Speicherorte sind verzahnt, da beide ja "nur" eine View auf A darstellen:

A = np.array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
B1 = A[::2]
B2 = A[1::2]
print(np.may_share_memory(B1, B2))
True

Das obige Beispiel ist ein falsch-positiv-Beispiel für may_share_memory in dem Sinn, dass jemand wegen der Ausgabe "True" denken könnte, dass die Arrays gemeinsamen Speicher hätten.



Dreidimensionale Arrays

Dreidimensionale Arrays sind vom Zugriff her etwas schwerer vorstellbar. Betrachten wir dazu das folgende Beispielarray:

import numpy as np
X = np.array(
    [[[3, 1, 2],
      [4, 2, 2]],
     [[-1, 0, 1],
      [1, -1, -2]],
     
     [[3, 2, 2],
      [4, 4, 3]],
     [[2, 2, 1],
      [3, 1, 3]]])
print(X.shape)
(4, 2, 3)

Wir sehen, dass dieses Array eine Shape (4, 2, 3) hat. Wir benutzen nun die Slicing-Funktionalität, um uns die Schnitte durch die Dimensionen zu veranschaulichen:

print("Dimension 0 with size ", X.shape[0])
for i in range(X.shape[0]):
    print(X[i,:,:])
    
print("\nDimension 1 with size ", X.shape[1])
for i in range(X.shape[1]):
    print(X[:,i,:])
    
print("\nDimension 2 with size ", X.shape[2])
for i in range(X.shape[2]):
    print(X[:,:,1])
Dimension 0 with size  4
[[3 1 2]
 [4 2 2]]
[[-1  0  1]
 [ 1 -1 -2]]
[[3 2 2]
 [4 4 3]]
[[2 2 1]
 [3 1 3]]
Dimension 1 with size  2
[[ 3  1  2]
 [-1  0  1]
 [ 3  2  2]
 [ 2  2  1]]
[[ 4  2  2]
 [ 1 -1 -2]
 [ 4  4  3]
 [ 3  1  3]]
Dimension 2 with size  3
[[ 1  2]
 [ 0 -1]
 [ 2  4]
 [ 2  1]]
[[ 1  2]
 [ 0 -1]
 [ 2  4]
 [ 2  1]]
[[ 1  2]
 [ 0 -1]
 [ 2  4]
 [ 2  1]]



Arrays mit Nullen und Einsen

Arrays können auf zwei Arten mit Nullen und Einsen initialisiert werden. Die Methode ones(t) hat als Parameter ein Tupel t mit der Shape des Arrays und erzeugt entsprechend ein Array mit Einsen. Defaultmäßig wird es mit Float-Einsen gefüllt. Wenn man Integer-Einsen benötigt, kann man den optionalen Parameter dtype auf "int" setzen:

In [ ]:
 
import numpy as np
E = np.ones((2, 3))
print(E)
F = np.ones((3, 4), dtype=int)
print(F)
[[1. 1. 1.]
 [1. 1. 1.]]
[[1 1 1 1]
 [1 1 1 1]
 [1 1 1 1]]

Was wir über die Methode ones() gesagt haben gilt analog für zeros(), wie wir im folgenden Beispiel erkennen können:

Z = np.zeros((2, 4))
print(Z)
Z = np.zeros((2, 4), dtype=int)
print(Z)
[[0. 0. 0. 0.]
 [0. 0. 0. 0.]]
[[0 0 0 0]
 [0 0 0 0]]

Es gibt noch eine andere interessante Möglichkeit ein Array mit Einsen oder Nullen zu erzeugen, wenn es die gleiche Shape wie ein anderes existierendes Array 'a' haben soll. Für diesen Zweck stellt Numpy die Methoden ones_like() und zeros_like() zur Verfügung:

x = np.array([2, 5, 18, 14, 4])
E = np.ones_like(x)
print(E)
Z = np.zeros_like(x)
print(Z)
[1 1 1 1 1]
[0 0 0 0 0]



Arrays kopieren


numpy.copy()

copy(obj, order='K')

Die Methode copy liefert vom gegebenen Objekt 'obj' eine Array-Kopie zurück.

Parameter Bedeutung
obj array-ähnliche Eingabedaten
order Die möglichen Werte sind{'C', 'F', 'A', 'K'}. Dieser Parameter kontrolliert das Speicher-Layout der Kopie. 'C' bedeutet C-Reihenfolge, 'F' Fortran-Reihenfolge, 'A' verhält sich wie 'F' falls das Objekt 'obj' in Fortran-Reihenfolge ist, ansonsten verhält sich 'A' wie 'C'. 'K' bedeutet, dass das Layout von 'obj' so nahe wie möglich realisiert werden soll.
import numpy as np
x = np.array([[42,22,12],[44,53,66]], order='F')
y = x.copy()
x[0,0] = 1001
print(x)
print(y)
[[1001   22   12]
 [  44   53   66]]
[[42 22 12]
 [44 53 66]]
print(x.flags['C_CONTIGUOUS'])
print(y.flags['C_CONTIGUOUS'])
False
True



ndarray.copy()

Es gibt auch noch eine ndarray-Methode 'copy', die direkt auf ein Array angewendet werden kann. Sie ist ähnlich wie die obige Funktion aber die Defaultwerte sind anders.

a.copy(order='C')

Liefert eine Kopie des Arrays 'a' zurück.

Parameter Bedeutung
order Gleich wie numpy.copy, aber 'C' ist der Default-Wert.
import numpy as np
x = np.array([[42,22,12],[44,53,66]], order='F')
y = x.copy()
x[0,0] = 1001
print(x)
print(y)
print(x.flags['C_CONTIGUOUS'])
print(y.flags['C_CONTIGUOUS'])
[[1001   22   12]
 [  44   53   66]]
[[42 22 12]
 [44 53 66]]
False
True



Identitäts-Array

In der linearen Algebra versteht man unter der Identitätsmatrix oder Einheitsmatrix eine quadratische Matrix, deren Hauptdiagonalelemente eins und deren Außerdiagonalelemente null sind.

Numpy bietet zwei Möglichkeiten solche Arrays zu erzeugen:


Die identity-Funktion

Wir können Identitäts-Arrays mit der Funktion identity generieren:

identity(n, dtype=None)

Parameter Bedeutung
n Eine Integer-Zahl, welche die Anzahl der Zeilen und Spalten der Ausgabe definiert, d.h. 'n' x 'n'
dtype Ein optionales Argument, welches den Datentyp des Ergebnisses definiert. Der Default ist 'float'

Die Ausgabe von identity ist ein n x n-Array, in dem die Elemente auf der hauptdiagonalen auf 1 gesetzt sind und alle anderen Elemente auf 0.

import numpy as np
np.identity(4)
Führt man obigen Code aus, erhält man folgendes Ergebnis:
array([[1., 0., 0., 0.],
       [0., 1., 0., 0.],
       [0., 0., 1., 0.],
       [0., 0., 0., 1.]])
np.identity(4, dtype=int) # equivalent to np.identity(3, int)
Der obige Code liefert folgendes Ergebnis:
array([[1, 0, 0, 0],
       [0, 1, 0, 0],
       [0, 0, 1, 0],
       [0, 0, 0, 1]])



Die eye-Funktion

Die Funktion eye bietet eine andere Möglichkeit Identitätsarrays aber auch allgemeine Diagonalarrays mit Einsen zu erzeugen. Die Ausgabe von eye ist ein zweidimensionales Array, in dem die Elemente auf der Hauptdiagonalen auf 1 gesetzt sind und alle anderen Elemente auf 0.

eye(N, M=None, k=0, dtype=float)

Parameter Bedeutung
N Eine Integer-Zahl, welche die Anzahl der Zeilen des Ausgebearrays bestimmt.
M Eine Integer-Zahl, welche die Spalten des Ausgebearrays bestimmt. Falls dieser Parameter nicht gesetzt ist oder None ist, wird er per Default auf 'N' gesetzt.
k mit 'k' wird die Position der Diagonalen gesetzt. Der Default ist 0. 0 bezeichnet die Hauptdiagonale. Ein positiver Wert bezeichnet eine obere Diagonale und ein negativer Wert eine untere Diagonale.
dtype Ein optionales Argument, welches den Datentyp des Ergebnisses definiert. Der Default ist 'float'.

eye liefert ein ndarray der Shape (N, M) zurück. Alle Elemente dieses Arrays sind 0 außer denen auf der 'k'-ten Diagonale, die auf 1 gesetzt sind.

import numpy as np
np.eye(5, 8, k=1, dtype=int)
Der obige Python-Code liefert Folgendes:
array([[0, 1, 0, 0, 0, 0, 0, 0],
       [0, 0, 1, 0, 0, 0, 0, 0],
       [0, 0, 0, 1, 0, 0, 0, 0],
       [0, 0, 0, 0, 1, 0, 0, 0],
       [0, 0, 0, 0, 0, 1, 0, 0]])

Die Arbeitsweise des Parameters 'd' von 'eye' illustrieren wir in folgendem Diagramm:

Arbeitsweise der 'eye'-Funktion mit dem Parameter 'k'



Übungen:

1) Erzeugen Sie ein beliebiges eindimensionales Array, welches Sie "v" nennen.

2) Erzeugen Sie nun ein neues Array, das aus den ungeraden Indizes des vorher erzeugten Arrays "v" besteht.

3) Erzeugen Sie aus 'v' eine Array in umgekehrter Reihenfolge.

4) Wie sieht die Ausgabe des folgenden Codes aus?

   a = np.array([1, 2, 3, 4, 5])
   b = a[1:4]
   b[0] = 200
   print(a[1])
   

5) Erzeugen Sie ein zweidimensionales Array mit dem Namen "m".

6) Erzeugen Sie nun ein neues Array aus 'm', in dem die Elemente von jeder Reihe in umgekehrter Reihenfolge sind.

7) Ein weiteres, in dem die Zeilen in vertauschter Reihenfolge sind.

8) Erzeugen Sie ein Array aus m, in dem sowohl die Zeilen als auch die Spalten in umgekehrter Reihenfolge sind.

9) Schneiden Sie die erste und die letzte Reihe und Spalte ab.



Lösungen zu den Übungen:

1) import numpy as np a = np.array([3,8,12,18,7,11,30])

2) odd_elements = a[1::2]

3) reverse_order = a[::-1]

4) Die Ausgabe lautet 200, weil der Teilbereichsoperator in Numpy Sichten (Views) und keine Kopien liefert.

5) m = np.array([ [11, 12, 13, 14], [21, 22, 23, 24], [31, 32, 33, 34]])

6) m[::,::-1]

7) m[::-1]

8) m[::-1,::-1]

9) m[1:-1,1:-1]