In der Welt der Datenanalyse und wissenschaftlichen Berechnung sind NumPy und Pandas zwei unverzichtbare Bibliotheken in Python. Aber warum sind sie so wichtig? In diesem Artikel werden wir die Gründe untersuchen, warum NumPy und Pandas in der Datenanalyse so weit verbreitet sind, welche Vorteile sie bieten und wie sie sich voneinander unterscheiden.
Warum NumPy?
NumPy, kurz für “Numerical Python”, ist eine Bibliothek, die effiziente Operationen auf großen, mehrdimensionalen Arrays und Matrizen ermöglicht. Hier sind einige Gründe, warum NumPy so beliebt ist:
Leistung: NumPy ist in C und Fortran geschrieben, was es extrem schnell macht. Es bietet Funktionen, die auf Vektorisierung basieren, wodurch Operationen auf Arrays viel schneller ausgeführt werden können als mit herkömmlichen Python-Listen.
Funktionalität: NumPy bietet eine breite Palette von Funktionen für mathem atische Operationen, lineare Algebra, Fourier-Transformationen und vieles mehr. Es ist die Grundlage für viele andere Bibliotheken wie SciPy, Matplotlib und Pandas.
Kompatibilität: Viele andere Bibliotheken in der Datenwissenschaft und maschinellen Lernen basieren auf NumPy, was es zu einem unverzichtbaren Werkzeug für die Arbeit mit Daten macht.
Einfachheit: NumPy bietet eine einfache und intuitive Syntax für die Arbeit mit Arrays, was es Anfängern leicht macht, sich in die Welt der Datenanalyse einzuarbeiten
Kurz:
“NumPy = schnelle Mathematik + feste Typen + große Reihungen” in Python
Beispiel
Stellen wir uns vor, wir wollen 10 Millionen Zahlen in einer Python Liste speichern.
Eine Python Liste aber:
Speichert die Werte irgendwo im Speicher und nicht unmittelbar hintereinander.
Speichert die Werte als Objekte, was zusätzlichen Speicherplatz benötigt.
Ist nicht für numerische Berechnungen optimiert, da jedes Objekt individuell behandelt werden muss.
Stellen wir uns vor, wie wollen zu jeder Zahl 10 hinzuaddieren. Mit einer Python Liste müssten wir eine Schleife verwenden, um durch die Liste zu iterieren und die Addition für jedes Element durchzuführen, was sehr langsam sein kann.
import time# Erstellen einer Liste mit 10 Million Zahlenmy_list =list(range(10_000_000))# Startzeitstart_time = time.time()# Hinzufügen von 10 zu jedem Element in der Listefor i inrange(len(my_list)): my_list[i] +=10# Endzeitend_time = time.time()print(f"Zeit für die Addition in der Liste: {end_time - start_time:0.4} Sekunden")
Zeit für die Addition in der Liste: 0.6944 Sekunden
Die angegebe Laufzeit hängen natürlich von den Rechner und den Versionen der Software ab.
Der Grund wieso das alles so langsam ist, liegt unter anderem daran, dass die 10.000.000 Einträge in der Python Liste in der Schleife durchlaufen wird. Und das ist langsam, denn die ergentliche Liste ist eine Liste von Verweisen auf die in einem Objekt gespeicherten eigentlichen Werte. Python geht also (schnell) eine Liste von Referenzen durch, muss aber jedesmal (irgendwo) im Speicher den eigentlichen Werte suchen, dann anpassen und dann in der (Referenz-)Liste den nächsten suchen.
Die Lösung dieses Problems ist NumPy.
Mit NumPy können wir ein Array erstellen, das die Zahlen direkt hintereinander im Speicher speichert und die Werte als numerische Datentypen behandelt, da es davon ausgeht, dass diese alle vom selben Datentyp sind. (Python schaut erst in den Metadaten des Objekts nach, ob dem so ist. Das kostet auch Zeit.) Dadurch können wir die Addition von 10 zu jedem Element in einem einzigen Schritt durchführen, ohne eine Python-Schleife zu verwenden, was viel schneller ist.
Okay, wir durchlaufen schon eine Schleife, aber diese muss nicht nach dem eigentlichen Objekt mit dem Eintrag in Speicher suchen. Denn im Array sind alle Objekte vom selbern Datentyp und belegen immer den selber Speicherplatz und das hintereinander. Wir springen also direkt zum nächsten Eintrag, ändern und gehen weiter. Das ist deutlich schneller und ermöglicht das die Verarbeitung optimiert ist. NumPy nutzt auch Vektorisierung, um Operationen auf Arrays effizienter durchzuführen, indem es sie in C (oder Fortran) ausführt, anstatt in Python.
import numpy as npimport time# Erstellen eines NumPy-Arrays mit 10 Million Zahlenmy_array = np.arange(10_000_000)# Startzeitstart_time = time.time()# Hinzufügen von 10 zu jedem Element im Arraymy_array +=10# Endzeitend_time = time.time()print(f"Zeit für die Addition im NumPy-Array: {end_time - start_time:0.4} Sekunden.")
Zeit für die Addition im NumPy-Array: 0.009774 Sekunden.
Auch hier hängt die angegebene Laufzeit vom Rechner und den Software Versionen ab. Aber die Tendenzen zeigen sich hier schon klar. NumPy ist deutlich schneller als reines Python.
Darum ist NumPy die Grundlage für die Pakete:
Tensoflow
PyTorch
Scikit-learn
SciPy
JAX
u.v.m.
Ein paar NumPy Grundlagen
NumPy Arrays erstellen
import numpy as np# Erstellen eines 1D-Arraysarray_1d = np.array([1, 2, 3, 4, 5])print(array_1d)
Intern werden optimierte C- oder Fortran-Code ausgeführt, der direkt auf die Daten im Speicher zugreift. Dies ermöglicht es NumPy, Operationen auf großen Arrays viel schneller durchzuführen als herkömmliche Python-Listen, die in einer Schleife verarbeitet werden müssen.
Deshalb werden im ML und DL die meisten Operationen auf NumPy Arrays ausgeführt. Dinge wie “scaling” und Matrix-Operationen werden so sehr viel schneller als im reinen Python.
Reshaping (umorganisieren von NumPy Arrays)
import numpy as np# Erstellen eines 1D-Arrays mit 12 Elementenarray_1d = np.arange(12) +1print("Ein 1D-Array:", array_1d)
Ein 1D-Array: [ 1 2 3 4 5 6 7 8 9 10 11 12]
# Reshaping in ein 2D-Array mit 3 Zeilen und 4array_2d = array_1d.reshape(3, 4)print("Reshaped Array (3x4):\n", array_2d)
Nahezu alle ML und DL modelle nutzen das Reshaping von Arrays, um die Daten in die richtige Form zu bringen, damit sie von den Modellen verarbeitet werden können. Zum Beispiel müssen Bilder oft in 4D-Arrays umgeformt werden, bevor sie in ein Convolutional Neural Network (CNN) eingespeist werden können.
Jedoch wird dabei niemals die Daten ansich verändert, sondern nur die Art und Weise, wie sie organisiert und interpretiert werden. Das Reshaping ermöglicht es, die Daten in einer Form zu präsentieren, die für die Verarbeitung durch ML-Modelle optimal ist, ohne die zugrunde liegenden Werte zu verändern.
Natürlich geht das nur, wenn die Anzahl der Elemente im ursprünglichen Array mit der Anzahl der Elemente im neuen Array übereinstimmt. Das bedeutet, dass die Gesamtzahl der Elemente vor und nach dem Reshaping gleich sein muss, damit die Daten korrekt umorganisiert werden können.
Das wird oft in der Praxis genutzt in der Vorverarbeitung von Daten (pre-processing), um sicherzustellen, dass die Daten die richtige Form haben, bevor sie in ein ML-Modell eingespeist werden.
Warum Pandas?
Pandas ist eine Bibliothek, die speziell für die Datenanalyse und -manipulation entwickelt wurde. Der Name leitet sich vom englischen “panel datas”, eine ökonometrischen Bezeichnung für Datentabellen, ab. Hier sind einige Gründe, warum Pandas so wichtig ist:
Datenstrukturen: Pandas bietet zwei Hauptdatenstrukturen, den DataFrame und die Series, die es ermöglichen, Daten in tabellarischer Form zu organisieren und zu manipulieren. Diese Strukturen sind besonders nützlich für die Arbeit mit heterogenen Daten.
Datenmanipulation: Pandas bietet eine Vielzahl von Funktionen für die Datenmanipulation, einschließlich Filtern, Gruppieren, Pivot-Tabellen und mehr. Es ermöglicht es Benutzern, komplexe Datenoperationen mit Leichtigkeit durchzuführen.
Datenbereinigung: Pandas bietet leistungsstarke Werkzeuge zur Bereinigung von Daten, einschließlich Funktionen zum Umgang mit fehlenden Werten, Duplikaten und Inkonstanzen in den Daten.
Integration: Pandas lässt sich nahtlos mit anderen Bibliotheken wie NumPy, Matplotlib und Scikit-learn integrieren, was es zu einem unverzichtbaren Werkzeug für die Datenanalyse macht.
Kurz:
“Pandas = Tabellenkalkulation + SQL + NumPy” in Python
Beispiel
NumPy ist wundervoll für mathematische Probleme, aber die Daten in der realen Welt sind oft unstrukturiert und heterogen. Hier kommt Pandas ins Spiel, um diese Daten in eine strukturierte Form zu bringen, die leichter zu analysieren ist.
Es gibt zwei grundlegende Datenstrukturen in Pandas: Series und DataFrame.
Eine Series ist eine eindimensionale, beschriftete Datenstruktur, die eine Liste von Werten enthält. Sie kann als eine Art erweiterte Liste betrachtet werden, die zusätzlich zu den Werten auch Indizes hat.
Ein DataFrame ist eine zweidimensionale, tabellarische Datenstruktur, die aus mehreren Series besteht. Es ist vergleichbar mit einer Tabelle in einer Datenbank oder einem Arbeitsblatt in Excel, wobei Zeilen und Spalten beschriftet sind.
Eine Series:
a 10
b 20
c 30
d 40
e 50
dtype: int64
Ein DataFrame:
Name Alter Stadt
0 Alice 25 New York
1 Bob 30 Los Angeles
2 Charlie 35 Chicago
3 David 40 Houston
4 Eve 45 Phoenix
Anschauen der Daten in einem DataFrame
import pandas as pd# Erstellen eines DataFramesmy_dataframe = pd.DataFrame({'Name': ['Alice', 'Bob', 'Charlie', 'David', 'Eve'],'Alter': [25, 30, 35, 40, 45],'Stadt': ['New York', 'Los Angeles', 'Chicago', 'Houston', 'Phoenix']})print("Ein DataFrame:\n", my_dataframe)# Anzeigen der ersten 3 Zeilenprint("Die ersten 3 Zeilen:\n", my_dataframe.head(3))# Anzeigen der letzten 2 Zeilenprint("Die letzten 2 Zeilen:\n", my_dataframe.tail(2))# Anzeigen der Spaltennamenprint("Spaltennamen:", my_dataframe.columns)# Anzeigen der Datenarten jeder Spalteprint("Datenarten:\n", my_dataframe.dtypes)# Anzeigen der Anzahl der Zeilen und Spaltenprint("Anzahl der Zeilen und Spalten:", my_dataframe.shape)# Anzeigen von statistischen Zusammenfassungen der numerischen Spaltenprint("Statistische Zusammenfassung:\n", my_dataframe.describe())# Anzeigen der Informationen über den DataFrame print("Informationen:\n", my_dataframe.info())
Ein DataFrame:
Name Alter Stadt
0 Alice 25 New York
1 Bob 30 Los Angeles
2 Charlie 35 Chicago
3 David 40 Houston
4 Eve 45 Phoenix
Die ersten 3 Zeilen:
Name Alter Stadt
0 Alice 25 New York
1 Bob 30 Los Angeles
2 Charlie 35 Chicago
Die letzten 2 Zeilen:
Name Alter Stadt
3 David 40 Houston
4 Eve 45 Phoenix
Spaltennamen: Index(['Name', 'Alter', 'Stadt'], dtype='str')
Datenarten:
Name str
Alter int64
Stadt str
dtype: object
Anzahl der Zeilen und Spalten: (5, 3)
Statistische Zusammenfassung:
Alter
count 5.000000
mean 35.000000
std 7.905694
min 25.000000
25% 30.000000
50% 35.000000
75% 40.000000
max 45.000000
<class 'pandas.DataFrame'>
RangeIndex: 5 entries, 0 to 4
Data columns (total 3 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 Name 5 non-null str
1 Alter 5 non-null int64
2 Stadt 5 non-null str
dtypes: int64(1), str(2)
memory usage: 252.0 bytes
Informationen:
None
Datenselektierung mit Pandas
Pandas bietet verschiedene Möglichkeiten, um Daten aus einem DataFrame auszuwählen, einschließlich der Verwendung von Spaltennamen, Zeilenindizes und Bedingungen. Hier sind einige Beispiele:
import pandas as pd# Erstellen eines DataFramesmy_dataframe = pd.DataFrame({'Name': ['Alice', 'Bob', 'Charlie', 'David', 'Eve'],'Alter': [25, 30, 35, 40, 45],'Stadt': ['New York', 'Los Angeles', 'Chicago', 'Houston','Phoenix']})print("Ein DataFrame:\n", my_dataframe)# Auswahl einer Spalteprint("Spalte 'Name':\n", my_dataframe['Name'])# Auswahl mehrerer Spaltenprint("Spalten 'Name' und 'Alter':\n", my_dataframe[['Name', 'Alter']])# Auswahl einer Zeile basierend auf dem Indexprint("Zeile mit Index 2:\n", my_dataframe.loc[2])# Auswahl von Zeilen basierend auf ihrer Positionprint("Die ersten 3 Zeilen:\n", my_dataframe.iloc[:3])# Auswahl von Zeilen basierend auf einer Bedingungprint("Zeilen, in denen das Alter größer als 30 ist:\n", my_dataframe[my_dataframe['Alter'] >30])# Auswahl von Zeilen basierend auf einer Bedingungprint("Zeilen, in denen das Alter größer als 30 und kleiner gleich 40 ist:\n", my_dataframe[(my_dataframe['Alter'] >30) & (my_dataframe['Alter'] <=40)])
Ein DataFrame:
Name Alter Stadt
0 Alice 25 New York
1 Bob 30 Los Angeles
2 Charlie 35 Chicago
3 David 40 Houston
4 Eve 45 Phoenix
Spalte 'Name':
0 Alice
1 Bob
2 Charlie
3 David
4 Eve
Name: Name, dtype: str
Spalten 'Name' und 'Alter':
Name Alter
0 Alice 25
1 Bob 30
2 Charlie 35
3 David 40
4 Eve 45
Zeile mit Index 2:
Name Charlie
Alter 35
Stadt Chicago
Name: 2, dtype: object
Die ersten 3 Zeilen:
Name Alter Stadt
0 Alice 25 New York
1 Bob 30 Los Angeles
2 Charlie 35 Chicago
Zeilen, in denen das Alter größer als 30 ist:
Name Alter Stadt
2 Charlie 35 Chicago
3 David 40 Houston
4 Eve 45 Phoenix
Zeilen, in denen das Alter größer als 30 und kleiner gleich 40 ist:
Name Alter Stadt
2 Charlie 35 Chicago
3 David 40 Houston
Datenmanipulation mit Pandas
Pandas bietet eine Vielzahl von Funktionen für die Datenmanipulation, einschließlich Filtern, Gruppieren, Pivot-Tabellen und mehr. Hier sind einige Beispiele:
import pandas as pd# Erstellen eines DataFramesmy_dataframe = pd.DataFrame({'Name': ['Alice', 'Bob', 'Charlie', 'David', 'Eve'],'Alter': [25, 30, 35, 40, 45],'Stadt': ['New York', 'Los Angeles', 'Chicago', 'Houston', 'Phoenix']})print("Ein DataFrame:\n", my_dataframe)# Filtern von Zeilen basierend auf einer Bedingungfiltered_df = my_dataframe[my_dataframe['Alter'] >30]print("Gefilterter DataFrame (Alter > 30):\n", filtered_df)# Gruppieren von Daten und Berechnen von Durchschnittsalter pro Stadtgrouped_df = my_dataframe.groupby('Stadt')['Alter'].mean()print("Durchschnittsalter pro Stadt:\n", grouped_df)# Erstellen einer Pivot-Tabellepivot_table = my_dataframe.pivot_table(values='Alter', index='Stadt', aggfunc='mean')print("Pivot-Tabelle (Durchschnittsalter pro Stadt):\n", pivot_table)
Ein DataFrame:
Name Alter Stadt
0 Alice 25 New York
1 Bob 30 Los Angeles
2 Charlie 35 Chicago
3 David 40 Houston
4 Eve 45 Phoenix
Gefilterter DataFrame (Alter > 30):
Name Alter Stadt
2 Charlie 35 Chicago
3 David 40 Houston
4 Eve 45 Phoenix
Durchschnittsalter pro Stadt:
Stadt
Chicago 35.0
Houston 40.0
Los Angeles 30.0
New York 25.0
Phoenix 45.0
Name: Alter, dtype: float64
Pivot-Tabelle (Durchschnittsalter pro Stadt):
Alter
Stadt
Chicago 35.0
Houston 40.0
Los Angeles 30.0
New York 25.0
Phoenix 45.0
Hinzufügen von Daten zu einem DataFrame
import pandas as pd# Erstellen eines DataFramesmy_dataframe = pd.DataFrame({'Name': ['Alice', 'Bob', 'Charlie', 'David', 'Eve'],'Alter': [25, 30, 35, 40, 45],'Stadt': ['New York', 'Los Angeles', 'Chicago', 'Houston', 'Phoenix']})print("Ein DataFrame:\n", my_dataframe)# Hinzufügen einer neuen Spaltemy_dataframe['Beruf'] = ['Ingenieur', 'Arzt', 'Lehrer', 'Künstler', 'Anwalt']print("DataFrame mit neuer Spalte 'Beruf':\n", my_dataframe)# Hinzufügen einer neuen Zeilenew_row = pd.Series({'Name': 'Frank', 'Alter': 50, 'Stadt': 'Miami', 'Beruf': 'Architekt'})my_dataframe = pd.concat([my_dataframe, new_row.to_frame().T], ignore_index=True)print("DataFrame mit neuer Zeile:\n", my_dataframe)
Ein DataFrame:
Name Alter Stadt
0 Alice 25 New York
1 Bob 30 Los Angeles
2 Charlie 35 Chicago
3 David 40 Houston
4 Eve 45 Phoenix
DataFrame mit neuer Spalte 'Beruf':
Name Alter Stadt Beruf
0 Alice 25 New York Ingenieur
1 Bob 30 Los Angeles Arzt
2 Charlie 35 Chicago Lehrer
3 David 40 Houston Künstler
4 Eve 45 Phoenix Anwalt
DataFrame mit neuer Zeile:
Name Alter Stadt Beruf
0 Alice 25 New York Ingenieur
1 Bob 30 Los Angeles Arzt
2 Charlie 35 Chicago Lehrer
3 David 40 Houston Künstler
4 Eve 45 Phoenix Anwalt
5 Frank 50 Miami Architekt
Fazit
NumPy und Pandas sind zwei der wichtigsten Bibliotheken in der Python-Datenanalyse. NumPy bietet eine leistungsstarke Grundlage für die Arbeit mit Arrays und mathematischen Operationen, während Pandas speziell für die Datenmanipulation und -analyse entwickelt wurde. Beide Bibliotheken ergänzen sich hervorragend und sind unverzichtbar für jeden, der in der Welt der Datenanalyse tätig ist.