# invisible from IPython.display import HTML, display import numpy as np np.core.arrayprint._line_width = 65 

Datentyp-Objekt: dtype


dtype

Veranschaulichung von dtype-Daten mit Europa-Daten-Bild Das Datentypobjekt 'dtype' ist eine Instanz der numpy.dtype-Klasse. Es kann mit numpy.dtype konstruiert werden.

Bis jetzt haben wir in unseren Beispielen von NumPy-Arrays nur grundlegende numerische Typen wie 'int' und 'float' benutzt. Diese NumPy-Arrays enthielten nur homogene Datentypen. dtype-Objekte werden aus einer Kombination von grundlegenden Datentypen erzeugt. Mit Hilfe von dtype sind wir in der Lage "Strukturierte Arrays" zu erzeugen, auch bekannt als "record arrays". Strukturierte Arrays statten uns mit der Möglichkeit aus verschiedene Datentypen in verschiedenen Spalten zu haben. Es gibt somit Ähnlichkeit zu Excel- oder CSV-Dokumenten. Dies ermöglicht es uns somit Daten wie in der folgenden Tabelle mit dtype zu erzeugen:

Land Bevölkerungsdichte      Fläche      Einwohner
Niederlande 393 41526 16,928,800
Belgien 337 30510 11,007,020
Vereinigtes Königreich 256 243610 62,262,000
Deutschland 233 357021 81,799,600
Liechtenstein 205 160 32,842
Italien 192 301230 59,715,625
Schweiz 177 41290 7,301,994
Luxemburg 173 2586 512,000
Frankreich 111 547030 63,601,002
Österreich 97 83858 8,169,929
Griechenland 81 131940 11,606,813
Irland 65 70280 4,581,269
Schweden 20 449964 9,515,744
Finnland 16 338424 5,410,233
Norwegen 13 385252 5,033,675

Bevor wir jedoch mit komplexen Daten wie den obigen starten, wollen wir dtype an einem sehr einfachen Beispiel einführen. Wir definieren einen Pixel-Datentyp, der einem numpy.uint8-Datentyp entspricht.

Die Elemente der Liste lst werden in Pixel-Typen gewandelt, um das zweidimensionale Array A zu erzeugen. Wir können sehen, dass dabei auch Float-Werte automatisch in Pixel-Datentypen, also numpy.uint8, gewandelt werden.

import numpy as np Pixel = np.dtype(np.uint8) print(Pixel) lst = [ [115, 230.9, 229.2, 234], [117, 229, 232.1, 235], [116, 140, 141, 142] ] A = np.array(lst, dtype=Pixel) print(A) 
uint8 [[115 230 229 234] [117 229 232 235] [116 140 141 142]] 

Im vorigen Beispiel haben wir lediglich einen neuen Namen für einen Basisdatentyp eingeführt. Damit kann man beispielsweise die Lesbarkeit und Verständlichkeit eines Programmes erhöhen. Dies hat noch nichts mit "Strukturierten Arrays" zu tun, die wir am Anfang dieses Kapitels

unseres Tutorials

erwähnt hatten.

Strukturierte Arrays

ndarrays sind homogene Datenobjekte, d.h. alle Elemente eines Arrays haben den gleichen Datentyp. Der Datentyp dtype hingegen erlaubt es uns, spaltenweise Typen zu deklarieren.

Nun gehen wir den ersten Schritt in Richtung Implementierung der Tabelle europäischer Länder mit den Informationen über Fläche, Bevölkerung und Bevölkerungsdichte.

Wir erzeugen ein strukturiertes Array mit einer Spalte density. Den Datentyp definieren wir als np.dtype([('density', np.int)]). Diesen Datentyp weisen wir der Variablen Density zu. Wir haben die Variable groß geschrieben, damit man sieht, dass es einen Unterschied gibt zu dem density in der Typdefinition selbst. Den Datentyp Density benutzen wir dann in der Definition des NumPy-Arrays, in dem wir die ersten drei Werte benutzen:

import numpy as np Density = np.dtype([('density', np.int32)]) x = np.array([(393,), (337,), (256,)], dtype=Density) print(x) print("\nDie interne Darstellung:") print(repr(x)) 
[(393,) (337,) (256,)] Die interne Darstellung: array([(393,), (337,), (256,)], dtype=[('density', '<i4')]) 

Wir können auf die density-Spalte zugreifen, indem wir als Schlüssel density eingeben. Es ähnelt einem

Dictionary-Zugriff

in Python:

print(x['density']) 
[393 337 256] 

Man wird sich vielleicht wundern, dass wir np.int32 in unserer Definition benutzt haben, aber dass die interne Repräsentierung <i4 zeigt.

In einer dtype-Definition können wir den Typ direkt verwenden, also beispielsweise np.int32, oder wir können einen String benutzen, z.B. i4.

In unserem Beispiel hätten wir unseren dtype auch wie folgt definieren können:

Density = np.dtype([('density', 'i4')]) x = np.array([(393,), (337,), (256,)], dtype=Density) print(x) 
[(393,) (337,) (256,)] 

Das i steht für Integer, und die 4 bedeutet "4 Bytes". Was bedeutet aber das Kleiner-als-Zeichen vor der 4? Wir hätten ebensogut '<i4' schreiben können. Wir können einem Typ ein '<'- oder ein '>'-Zeichen voranstellen. '<' bedeutet, dass bei der Speicherorganisation Little-Endian verwendet wird, und '>' bedeutet entsprechend, dass Big-Endian verwendet wird. Ohne Präfix wird die natürliche Byte-Reihenfolge des Systems verwendet. Wir demonstrieren dies im folgenden Beispiel, indem wir eine Gleitkommazahl mit doppelter Genauigkeit (double precision floating-point) in verschiedenen Byte-Reihenfolgen definieren:

# little-endian ordering dt = np.dtype('<d') print(dt.name, dt.byteorder, dt.itemsize) # big-endian ordering dt = np.dtype('>d') print(dt.name, dt.byteorder, dt.itemsize) # native byte ordering dt = np.dtype('d') print(dt.name, dt.byteorder, dt.itemsize) 
float64 = 8 float64 > 8 float64 = 8 

Das Gleichheitszeichen '=' steht für die natürliche Byte-Reihenfolge ('native byte ordering'), definiert durch das Betriebssystem. In unserem Fall bedeutet dies Little-Endian, weil wir uns auf einem Linux-Rechner befinden.

Eine andere Sache in unserem Density-Array könnte verwirrend sein. Wir definierten das Array mit einer Liste, die 1-Tupels enthält. Vielleicht fragen Sie sich nun, ob es möglich ist Tupels und Listen austauschbar zu verwenden? Dies ist nicht möglich. Die Tupels werden verwendet um die Records zu definieren - in unserm Fall bestehen diese nur aus der Bevölkerungsdichte ('density') -, und die Liste ist der 'Container' für die Records. Die Tupel definieren die atomaren Elemente der Struktur und die Listen die Dimensionen.

Nun werden wir die Ländernamen, die Flächen und die Populationen zu unserem Typ hinzufügen:

dt = np.dtype([('country', 'S20'), ('density', 'i4'), ('area', 'i4'), ('population', 'i4')]) population_table = np.array([('Netherlands', 393, 41526, 16928800), ('Belgium', 337, 30510, 11007020), ('United Kingdom', 256, 243610, 62262000), ('Germany', 233, 357021, 81799600), ('Liechtenstein', 205, 160, 32842), ('Italy', 192, 301230, 59715625), ('Switzerland', 177, 41290, 7301994), ('Luxembourg', 173, 2586, 512000), ('France', 111, 547030, 63601002), ('Austria', 97, 83858, 8169929), ('Greece', 81, 131940, 11606813), ('Ireland', 65, 70280, 4581269), ('Sweden', 20, 449964, 9515744), ('Finland', 16, 338424, 5410233), ('Norway', 13, 385252, 5033675)], dtype=dt) print(x[:4]) 
[(393,) (337,) (256,)] 

Wir können auf jedes Element individuell zugreifen:

print(population_table['density']) print(population_table['country']) print(population_table['area'][2:5]) 
[393 337 256 233 205 192 177 173 111 97 81 65 20 16 13] [b'Netherlands' b'Belgium' b'United Kingdom' b'Germany' b'Liechtenstein' b'Italy' b'Switzerland' b'Luxembourg' b'France' b'Austria' b'Greece' b'Ireland' b'Sweden' b'Finland' b'Norway'] [243610 357021 160] 

Die Städtenamen sind Instanzen der NumPy-Klasse numpy.bytes_. Man kann sie mit der Funktion str wieder in Unicode-Strings wandeln. Weiter unten werden wir auch sehen, wie man direkt mit Unicode-Strings in dtype-Arrays arbeitet.

s = population_table['country'][0] print(s, type(s)) s = str(s) print(s, type(s)) 
b'Netherlands' <class 'numpy.bytes_'> b'Netherlands' <class 'str'> 



Ein- und Ausgabe von strukturierten Arrays

In den meisten Applikationen ist es notwendig, die Daten aus einem Programm in einer Datei zu speichern. Wir werden nun unser zuvor erzeugtes Array in einer Datei mit dem Kommando savetxt speichern. Eine detaillierte Einführung in diese Thematik findet man im Kapitel

Lesen und Schreiben von Daten-Dateien

np.savetxt("population_table.csv", population_table, fmt="%s;%d;%d;%d", delimiter=";") 

Sehr wahrscheinlich wird man zu einem späteren Zeitpunkt die Daten der eben gespeicherten Datei wieder einlesen wollen. Dies können wir mit dem Kommando genfromtxt bewerkstelligen.

dt = np.dtype([('country', np.unicode, 20), ('density', 'i4'), ('area', 'i4'), ('population', 'i4')]) x = np.genfromtxt("population_table.csv", dtype=dt, delimiter=";") print(x) 
[("b'Netherlands'", 393, 41526, 16928800) ("b'Belgium'", 337, 30510, 11007020) ("b'United Kingdom'", 256, 243610, 62262000) ("b'Germany'", 233, 357021, 81799600) ("b'Liechtenstein'", 205, 160, 32842) ("b'Italy'", 192, 301230, 59715625) ("b'Switzerland'", 177, 41290, 7301994) ("b'Luxembourg'", 173, 2586, 512000) ("b'France'", 111, 547030, 63601002) ("b'Austria'", 97, 83858, 8169929) ("b'Greece'", 81, 131940, 11606813) ("b'Ireland'", 65, 70280, 4581269) ("b'Sweden'", 20, 449964, 9515744) ("b'Finland'", 16, 338424, 5410233) ("b'Norway'", 13, 385252, 5033675)] 

Statt genfromtxt kann man auch loadtxt verwenden:

dt = np.dtype([('country', np.unicode, 25), ('density', 'i4'), ('area', 'i4'), ('population', 'i4')]) x = np.loadtxt("population_table.csv", dtype=dt, delimiter=";") print(x) 
[("b'Netherlands'", 393, 41526, 16928800) ("b'Belgium'", 337, 30510, 11007020) ("b'United Kingdom'", 256, 243610, 62262000) ("b'Germany'", 233, 357021, 81799600) ("b'Liechtenstein'", 205, 160, 32842) ("b'Italy'", 192, 301230, 59715625) ("b'Switzerland'", 177, 41290, 7301994) ("b'Luxembourg'", 173, 2586, 512000) ("b'France'", 111, 547030, 63601002) ("b'Austria'", 97, 83858, 8169929) ("b'Greece'", 81, 131940, 11606813) ("b'Ireland'", 65, 70280, 4581269) ("b'Sweden'", 20, 449964, 9515744) ("b'Finland'", 16, 338424, 5410233) ("b'Norway'", 13, 385252, 5033675)] 



Unicode-Strings in Arrays

Wir hatten ja bereits darauf hingewiesen, dass die Strings in unserem vorigen Beispielarray ein kleines b als Präfix hatten. Dies kam dadurch, dass wir in unserer dtype-Definition ('country', 'S20') geschrieben und dadurch unsere Ländernamen als Binärstrings definiert hatten.

Um Unicode-Strings zu erhalten, müssen wir die Definition in ('country', np.unicode, 20) umändern. Wir ändern die Definition für population_table wie folgt:

dt = np.dtype([('country', np.unicode, 25), ('density', 'i4'), ('area', 'i4'), ('population', 'i4')]) population_table = np.array([ ('Netherlands', 393, 41526, 16928800), ('Belgium', 337, 30510, 11007020), ('United Kingdom', 256, 243610, 62262000), ('Germany', 233, 357021, 81799600), ('Liechtenstein', 205, 160, 32842), ('Italy', 192, 301230, 59715625), ('Switzerland', 177, 41290, 7301994), ('Luxembourg', 173, 2586, 512000), ('France', 111, 547030, 63601002), ('Austria', 97, 83858, 8169929), ('Greece', 81, 131940, 11606813), ('Ireland', 65, 70280, 4581269), ('Sweden', 20, 449964, 9515744), ('Finland', 16, 338424, 5410233), ('Norway', 13, 385252, 5033675)], dtype=dt) print(population_table[:4]) 
[('Netherlands', 393, 41526, 16928800) ('Belgium', 337, 30510, 11007020) ('United Kingdom', 256, 243610, 62262000) ('Germany', 233, 357021, 81799600)] 

Umbenennen von Spaltennamen

Nun wollen wir die Spaltennamen in deutsche Bezeichnungen umbenennen. Auf die Spaltennamen kann man mit der Property names von dtype zugreifen:

print(population_table.dtype.names) 
('country', 'density', 'area', 'population') 

Das Umbenennen gestaltet sich denkbar einfach. Man weist dieser Property einfach ein neues Tupel mit den neuen Namen zu:

population_table.dtype.names = ('Land', 'Bevölkerungsdichte', 'Fläche', 'Bevölkerung') print(population_table['Land']) 
['Netherlands' 'Belgium' 'United Kingdom' 'Germany' 'Liechtenstein' 'Italy' 'Switzerland' 'Luxembourg' 'France' 'Austria' 'Greece' 'Ireland' 'Sweden' 'Finland' 'Norway'] 

Spaltenwerte austauschen

Nun wollen wir auch die Ländernamen von Englisch nach Deutsch übersetzen. Dazu erzeugen wir eine Liste lands. Wir können diese mit np.array in ein Array wandeln und dann die bisherige Spalte population_table['Land'] komplett austauschen:

lands = ['Niederlande', 'Belgien', 'Vereinigtes Königreich', 'Deutschland', 'Liechtenstein', 'Italien', 'Schweiz', 'Luxemburg', 'Frankreich', 'Österreich', 'Griechenland', 'Irland', 'Schweden', 'Finnland', 'Norwegen'] population_table['Land'] = np.array(lands, dtype='<U25') print(population_table) 
[('Niederlande', 393, 41526, 16928800) ('Belgien', 337, 30510, 11007020) ('Vereinigtes Königreich', 256, 243610, 62262000) ('Deutschland', 233, 357021, 81799600) ('Liechtenstein', 205, 160, 32842) ('Italien', 192, 301230, 59715625) ('Schweiz', 177, 41290, 7301994) ('Luxemburg', 173, 2586, 512000) ('Frankreich', 111, 547030, 63601002) ('Österreich', 97, 83858, 8169929) ('Griechenland', 81, 131940, 11606813) ('Irland', 65, 70280, 4581269) ('Schweden', 20, 449964, 9515744) ('Finnland', 16, 338424, 5410233) ('Norwegen', 13, 385252, 5033675)] 


Komplexeres Beispiel

In den bisherigen Beispielen haben wir unsere Arrays direkt erzeugt. Normalerweise müssen wir uns jedoch die Daten für unsere strukturierten Arrays aus Datenbanken oder Dateien beschaffen.

Wir werden nun die Liste benutzen, die wir im Kapitel über Dateimanagement erzeugt und gespeichert hatten. Die Liste hatten wir mit Hilfe von pickle.dumpy in der Datei cities_and_times.pkl gespeichert.

Die erste Aufgabe besteht also darin, diese Datei wieder zu ent"pickeln":

import pickle fh = open("cities_and_times.pkl", "br") cities_and_times = pickle.load(fh) for i in range(5): print(cities_and_times[i]) 
('Amsterdam', 'Sun', (8, 52)) ('Anchorage', 'Sat', (23, 52)) ('Ankara', 'Sun', (10, 52)) ('Athens', 'Sun', (9, 52)) ('Atlanta', 'Sun', (2, 52)) 

Nun wandeln wir unsere Daten in ein strukturiertes Array:

time_type = np.dtype([('city', 'U30'), ('day', 'U3'), ('time', [('h', int), ('min', int)])]) times = np.array( cities_and_times , dtype=time_type) print(times[:4]) 
[('Amsterdam', 'Sun', ( 8, 52)) ('Anchorage', 'Sat', (23, 52)) ('Ankara', 'Sun', (10, 52)) ('Athens', 'Sun', ( 9, 52))] 
lst = [] for row in times: t = row[2] t = f"{t[0]:02d}:{t[1]:02d}" lst.append((row[0], row[1], t)) time_type = np.dtype([('city', 'U30'), ('day', 'U3'), ('time', 'U5')]) times2 = np.array( lst , dtype=time_type) print(times2[:10]) 
[('Amsterdam', 'Sun', '08:52') ('Anchorage', 'Sat', '23:52') ('Ankara', 'Sun', '10:52') ('Athens', 'Sun', '09:52') ('Atlanta', 'Sun', '02:52') ('Auckland', 'Sun', '20:52') ('Barcelona', 'Sun', '08:52') ('Beirut', 'Sun', '09:52') ('Berlin', 'Sun', '08:52') ('Boston', 'Sun', '02:52')] 

Nun wollen wir diese Daten in einer csv-Datei speichern. Leider können wir die Funktion np.savetxt nicht nutzen, da diese Funktion nicht mit Unicode-Strings zurechtkommt. Wir benutzen deshalb die normale write-Methode eines File-Streams:

with open("cities_and_times.csv", "w") as fh: for city_data in times2: fh.write(",".join(city_data) + "\n") 
# prog4book import numpy as np mytype = [('produktNr', np.int32), ('preise', np.float64)] produkte = np.array([(34765, 603.76), (45765, 439.93), (99661, 344.19), (12129, 129.39)], dtype=mytype) print(produkte[1]) print(produkte["produktNr"]) print(produkte[2]["preise"]) print(produkte) print(produkte.shape) 
(45765, 439.93) [34765 45765 99661 12129] 344.19 [(34765, 603.76) (45765, 439.93) (99661, 344.19) (12129, 129.39)] (4,) 
# prog4book verkaufszahlen = np.array([3, 5, 2, 1]) erlöse = produkte["preise"] * verkaufszahlen print("Erlöse pro Item: ", erlöse) print("Gesamterlös: ", erlöse.sum()) 
Erlöse pro Item: [1811.28 2199.65 688.38 129.39] Gesamterlös: 4828.700000000001 
# prog4book time_type = np.dtype( [('h', int), ('min', int), ('sec', int)]) times = np.array([(11, 38, 5), (14, 56, 0), ( 3, 9, 1)], dtype=time_type) print(times) print(times['h']) print(times['min']) print(times['sec']) 
[(11, 38, 5) (14, 56, 0) ( 3, 9, 1)] [11 14 3] [38 56 9] [5 0 1] 
# prog4book np.column_stack((times['h'], times['min'], times['sec'])) 
Ausgabe: :

array([[11, 38, 5], [14, 56, 0], [ 3, 9, 1]])
# prog4book time_temp_type = np.dtype( np.dtype([('time', [('h', int), ('min', int), ('sec', int)]), ('temperature', float)] )) time_temp = np.array( [((11, 42, 17), 20.8), ((13, 19, 3), 23.2), ((14, 50, 29), 24.6)], dtype=time_temp_type) print(time_temp) print(time_temp['time']) print(time_temp['time']['h']) print(time_temp['temperature']) 
[((11, 42, 17), 20.8) ((13, 19, 3), 23.2) ((14, 50, 29), 24.6)] [(11, 42, 17) (13, 19, 3) (14, 50, 29)] [11 13 14] [20.8 23.2 24.6] 
# prog4book with open("time_temp.csv", "w") as fh: for row in time_temp: zeit = [f"{el:02d}" for el in row[0]] zeit = ":".join(zeit) fh.write(zeit + " " + str(row[1]) + "\n") !cat time_temp.csv 
11:42:17 20.8 13:19:03 23.2 14:50:29 24.6 
box

Numerisches Python

Die Bücher zur Webseite

Bücher zur Webseite

Im Hanser-Verlag sind vier Bücher von Bernd Klein und Philip Klein erschienen, die auf den Inhalten dieser Webseite aufbauen, aber auch über die Inhalte hinausgehen. Es lohnt sich also die Bücher zu kaufen, womit Sie außerdem diese Webseite unterstützen!

Einführung in Python3

Einführung in Python von Bernd Klein
Zum Online-Shop des Hanser-Verlages, wo Sie das Buch versandkostenfrei bestellen können!


Numerisches Python: Arbeiten mit NumPy, Matplotlib und Pandas

Bernd Klein: Python-Buch Numerisches Python Buch kaufen

Bernd Klein, Philip Klein:
Funktionale Programmierung mit Python

Bernd Klein, Philip Klein: Funktionale Programmierung mit Python Buch kaufen Python-Grundlagen | eLearning
Mit dem Hanser eCampus „Python-Grundlagen“ erhalten Einsteiger:innen eine Einführung in die Programmiersprache Python.

Python Grundlagen: elearning, Bernd Klein Buch kaufen



Bücher kaufen

Wenn Ihnen diese Webseite gefällt, - was wir natürlich sehr hoffen, - dann können Sie meine Arbeit unterstützen, wenn Sie eines meiner Bücher oder beide Bücher kaufen oder weiterempfehlen.

Die Bücher können Sie über jede Buchhandlung in Ihrer Nähe beziehen. Alternativ können Sie sie auch direkt über den Hanser-Verlag beziehen:
Bücher von Bernd Klein und Philip Klein

Spenden

Ihre Unterstützung ist dringend benötigt. Diese Webseite ist frei von Werbeblöcken und -bannern! So soll es auch bleiben! Dazu benötigen wir Ihre Unterstützung:

Weshalb wir Ihre Spende dringend benötigen erfahren Sie hier



Definition von Datentypes


In einer Programmiersprache stellen Datentypen eine Klassifikation auf der Menge aller möglichen Datentypen dar. Diese Klassifikation basiert auf den möglichen WErten dieser Typen und den Operationen, die man auf ihnen anwenden kann. Die meisten Programmiersprachen sind mit Datentypen wie integer, real, float oder boolean ausgestattet. Ein einem einführenden Kapitel unseres Tutorials erfahren Sie mehr über "Datentypen und Variablen" in Python.

 


Suchen in dieser Webseite:

Webseite durchsuchen:

English Version / Englische Übersetzung

This chapter is also available in our English Python tutorial: Data Type Objects, dtype

Schulungen

Wenn Sie Python schnell und effizient lernen wollen, empfehlen wir den Kurs Bodenseo, Linux, Python und viele andere Kurse
Einführung in Python
von Bodenseo. Dieser Kurs wendet sich an totale Anfänger, was Programmierung betrifft. Wenn Sie bereits Erfahrung mit Python oder anderen Programmiersprachen haben, könnte der Python-Kurs für Fortgeschrittene der geeignete Kurs sein.

Python Courses


For those who prefer Python training courses in English: All our Python classes are available in English as well: Python Courses



Dem Autor Bernd Klein auf Facebook folgen:


Bernd Klein on Facebook

Spenden

Ihre Unterstützung ist dringend benötigt. Diese Webseite ist frei von Werbeblöcken und -bannern! So soll es auch bleiben! Dazu benötigen wir Ihre Unterstützung:

Weshalb wir Ihre Spende benötigen erfahren Sie hier

Spruch des Tages:

We can only see a short distance ahead, but we can see plenty there that needs to be done.
Alan Turing
(Wir können nur ein kleines Stück vorausschauen, aber wir sehen eine Menge dort, was noch zu tun ist.)


Und noch ein Spruch:

Es gibt Beweise, die auf die alten Griechen zurückgehen, und heutzutage immer noch gültig sind.
Andrew J. Wiles, Mathematiker

Hilfe

Diese Dokumentation zu Python mit Einführung und Tutorial wurde mit großer Sorgfalt erstellt und wird ständig erweitert. Dennoch können wir für die Korrektheit der Texte und der zahlreichen Beispiele keine Garantie übernehmen. Die Benutzung und Anwendung der Beispiele erfolgt auf eigenes Risiko. Wir freuen uns über alle Anregungen und Fehlerkorrekturen!



Datenschutzerklärung

Datenschutzerklärung nach DSGVO