Python-Praxis: Excel-Daten nutzen
Die pandas-Bibliothek bietet die Möglichkeit, mit Python Daten aus Excel-Arbeitsmappen auszulesen, zu bearbeiten und zu ändern.

(Bild: Heise Medien)
- Walter Saumweber
Programmseitige Zugriffe auf Excel sind für viele Anwendungsbereiche interessant. Daher verwundert es nicht, dass Python für diesen Zweck Bibliotheken zur Verfügung stellt. Außer pandas ist vor allem noch openpyxl zu nennen, wobei pandas selbst openpyxl in Teilen nutzt. Beide Bibliotheken unterstützen alle Excel-Formate, also auch den Makro-Dateityp .xlsm. Als Grundlage für die folgenden Codebeispiele dient eine Excel-Arbeitsmappe Demo.xlsx mit dem Arbeitsblatt Umsätze 2023. Die Tabelle ist mit je fünf Zeilen und Spalten bewusst einfach gehalten, aber natürlich lassen sich die folgenden Beispiele auch mit jeder anderen Excel-Arbeitsmappe nachvollziehen; die Größe des Tabellenblatts spielt dabei keine Rolle.
Die Beispieldateien zum Download
pandas installieren
Die pandas-Bibliothek ist nicht im Standardumfang von Python enthalten und lässt sich auf der Konsole mit dem Befehl pip3 install pandas
für Python 3 nachinstallieren. Die IDE PyCharm macht das Installieren von Bibliotheken besonders einfach. Es erkennt, falls eine Bibliothek nicht vorhanden ist, und bietet die Installation automatisch an. Dazu schreibt man den import-Befehl so in den Editor, als ob die Bibliothek schon vorhanden wäre. Beim Hovern mit der Maus über den rot unterkringelten Namen erscheint dann ein Pop-up-Fenster mit dem install-Befehl.
Die Bibliothek pandas nutzt wiederum die Bibliotheken NumPy und openpyxl, die die Installation von pandas normalerweise automatisch enthält. Es ist jedoch sinnvoll, sich davon zu überzeugen und sie gegebenenfalls nachzuinstallieren.
(Bild:Â Walter Saumweber)
Daten aus einem Excel-Tabellenblatt einlesen
Das Auslesen von Daten aus einem Excel-Tabellenblatt geschieht nach dem Import von pandas auf bequeme Weise mit der Funktion read_excel()
. Als ersten Parameter übergibt man den Namen der auszulesenden Excel-Datei, gegebenenfalls mit Pfad. Standardmäßig, ohne weitere Parameter, liest read_excel()
alle Daten des ersten Tabellenblatts ein.
import pandas
data_frame = pandas.read_excel('Demo.xlsx')
Die Funktion speichert die gelesenen Excel-Daten in einem DataFrame (Klasse pandas.core.frame.DataFrame
), und zwar zweidimensional, also praktisch wie in einem Excel-Arbeitsblatt. Somit enthält beispielsweise data_frame['I. Quartal'][0]
den Wert der ersten Zelle der Spalte I. Quartal. Im Arbeitsblatt von Demo.xlsx ist das der Umsatz des Bezirks A im ersten Quartal (Zelle B2).
Um sich einen Ăśberblick ĂĽber die Struktur der Daten zu verschaffen, kann man mit print(data_frame)
den kompletten DataFrame ausgeben oder mit print(data_frame['<Spaltenname>'])
nur die Daten einer Spalte, beispielsweise print(data_frame['I. Quartal'])
. Ausgegeben werden zum Beispiel auch die Indizes der Zeilen, beginnend bei 0 unter den Spaltennamen. Die Spalten mĂĽssen dagegen immer mit Namen, also durch Angabe eines Strings, referenziert werden. Falls eine Spalte nicht existiert, stellt sich ein KeyError ein. FĂĽr den Fall, dass eine Spalte im Excel-Tabellenblatt einmal umbenannt wird, ist eine diesbezĂĽgliche Ausnahmebehandlung sinnvoll:
try:
print(data_frame['I. Quartal'])
except KeyError:
print('Die Spalte existiert nicht')
Standardmäßig interpretiert die Funktion read_excel()
die Daten der ersten Zeile eines Excel-Tabellenblatts als SpaltenĂĽberschriften. FĂĽr Zellen, die in dieser Zeile leer sind, speichert der DataFrame den Wert Unnamed: <Index>
, fĂĽr die erste Zelle in der Beispieltabelle folglich den Wert Unnamed: 0
. data_frame['Unnamed: 0'][<Index>]
referenziert die Zeilenüberschriften dieser Tabelle – mit data_frame['Unnamed: 0'][2]
erhält man beispielsweise den Bezirk C
.
(Bild:Â Walter Saumweber)
PrĂĽfen, ob eine Excel-Zelle leer ist
Einfache Datenzellen, die leer sind, werden im DataFrame mit nan
(für „not a number“) gefüllt (in der Ausgabe erscheint jedoch das bekannte NaN
). Daher erhalten Developer kein korrektes Ergebnis, wenn sie im Python-Code auf einen Leerstring prĂĽfen. Beispielsweise ist die if-Bedingung if data_frame['I. Quartal'][1] == ''
nicht geeignet, um ĂĽber den erstellten DataFrame die zweite Zelle der Spalte I. Quartal dahin gehend zu prĂĽfen. Aber auch Vergleiche mit 'nan'
oder nan
fĂĽhren nicht zum Ziel.
Lösungen für dieses Problem gibt es mehrere. Zum einen stellt die pandas-Bibliothek für die Prüfung auf leere Zellen die Funktion isna
zur Verfügung. Dieser übergibt man den Teil des DataFrames, der die Zelle repräsentiert. Die Inhaltsprüfung von Zelle B3 könnte so aussehen:
if pandas.isna(data_frame['I. Quartal'][1]):
print('Die Zelle ist leer')
Die NumPy-Bibliothek bietet zum gleichen Zweck die Funktion isnan()
. Der Aufruf unterscheidet sich nicht von dem der Funktion isna(). Es gibt noch eine weitere, recht elegante Möglichkeit: Entwicklerinnen und Entwickler machen sich den Umstand zunutze, dass nan
das einzige Objekt ist, bei dem ein direkter Vergleich mit sich selbst ein False ergibt.
if data_frame['I. Quartal'][1] != data_frame['I. Quartal'][1]:
print('Die Zelle ist leer')
Parameter von read_excel()
FĂĽr Bedingungen, die nicht dem Standard entsprechen, stellt die Funktion read_excel()
verschiedene Parameter zur VerfĂĽgung. Der Parameter skiprows
kommt zum Einsatz, wenn die relevanten Daten nicht in der ersten Zeile beginnen. Der an skiprows
zugewiesene Wert steht fĂĽr die Anzahl der Zeilen, die read_excel()
ĂĽberspringen soll, zum Beispiel:
data_frame = pandas.read_excel('Demo.xlsx', skiprows=3)
Der Parameter sheet_name
bestimmt das einzulesende Tabellenblatt, mit der folgenden Anweisung das zweite Tabellenblatt der Beispiel-Arbeitsmappe.
data_frame = pandas.read_excel('Demo.xlsx', sheet_name='Umsätze 2024')
Anstelle des Namens eignet sich auch der Index, bei mehreren Tabellenblättern beispielsweise:
tabellenblaetter = [0, 1]
data_frames = pandas.read_excel('Demo.xlsx', sheet_name=tabellenblaetter)
In diesem Fall erzeugt read_excel()
ein Dictionary, das einen DataFrame für jedes Tabellenblatt enthält. Die Schlüssel bilden die Tabellenblätter-Indizes bzw. die Tabellenblattnamen. Die oben erzeugten DataFrames lassen sich mit data_frames[0]
und data_frames[1]
ansprechen.Der Parameter header
gibt die Zeile mit den SpaltenĂĽberschriften an, was erforderlich ist, wenn sie nicht die erste Zeile des Tabellenblatts ist. Die Angabe header=2
bedeutet zum Beispiel, dass sich die ZeilenĂĽberschriften in der dritten Zeile des Tabellenblatts befinden. header=None
teilt der read_excel()
mit, dass die Excel-Tabelle keine Spaltenüberschriften enthält. Unabhängig davon weist names
einer Liste die gewĂĽnschten Spaltennamen zu:
spalten = ['', 'I/24', 'II/24', 'III/24', 'IV/24']
data_frame = pandas.read_excel('Demo.xlsx', names=spalten)
print(data_frame)
Die Ausgabe sieht so aus:
I/24 II/24 III/24 IV/24
0 Bezirk A 19500 13500 17700 28000
1 Bezirk B 18400 25100 13600 21500
2 Bezirk C 9700 20000 29000 18500
3 Bezirk D 15800 14900 17200 16000
Wichtig ist dabei: read_excel()
erwartet in der names
-Liste fĂĽr jede Spalte genau eine Ăśberschrift, auch fĂĽr Zellen, die in der Ăśberschriftenzeile leer sind. Da die Ăśberschriftenzeile in der Excel-Tabelle fĂĽnf Spalten umfasst, muss auch die names
-Liste genau fünf Elemente enthalten, andernfalls würde sich ein ValueError einstellen („Number of passed names did not match number of header fields in the file“).
Es ist aber zulässig – wie hier beim ersten Element geschehen – einen Leerstring zuzuweisen. In diesem Fall enthält der DataFrame für diese Spalte tatsächlich keine Überschrift, und nicht etwa den Text „Unnamed: “ mit anschließendem Spaltenindex, den read_excel()
bei fehlenden SpaltenĂĽberschriften automatisch zuweist, wenn die Funktion ohne names-Parameter aufgerufen wird.
Allerdings definiert names
auch fĂĽr Spalten ohne Ăśberschrift eine solche.
spalten = ['Verkaufsbezirke', 'I/24', 'II/24', 'III/24', 'IV/24']
Ein bisschen Vorsicht ist bei der gemeinsamen Verwendung der Parameter skiprows
, names
und header
geboten, denn sie beeinflussen sich gegenseitig. Beispielsweise zählt die Überschriftenzeile der Excel-Tabelle beim skiprows
-Wert nicht mit, wenn beim read_excel()
-Aufruf gleichzeitig names
verwendet wird, und bei einem skiprows
-Wert von zum Beispiel 2 wĂĽrde die Angabe header=0
, ohne names
, bedeuten, dass die Ăśberschriftenzeile in der Excel-Tabelle nicht etwa die erste, sondern die dritte Zeile ist. Es ist also ratsam, sich in der Entwicklungsphase immer wieder davon zu ĂĽberzeugen, dass das Ergebnis den Erwartungen entspricht.
Der Parameter nrows
legt fest, wie viele Zeilen read_excel()
in den DataFrame einliest. Beispielsweise speichert read_excel()
mit nrows=2
im DataFrame zwei Datenzeilen plus Ăśberschriftenzeile. Beim Standardwert fĂĽr skiprows
(None beziehungsweise 0) sind das die ersten drei Zeilen der Beispieltabelle (die Ăśberschriftenzeile mitgerechnet). Falls ein Wert fĂĽr skiprows
angegeben ist, speichert read_excel()
die Zeilen ab der entsprechenden Stelle.
Mit dem Parameter usecols
lassen sich die einzulesenden Spalten beschränken. Diese müssen nicht unbedingt nebeneinanderliegen, sondern Entwicklerinnen und Entwickler können eine Liste mit Spaltennamen oder Indizes (aber nur eines von beiden) zuweisen. In Kombination mit names
mĂĽssen die durch diesen Parameter definierten Spaltennamen angegeben werden.
spalten = ['Verkaufsbezirke', 'I/23', 'II/23', 'III/23', 'IV/23']
data_frame = pandas.read_excel('Demo.xlsx', names=spalten, usecols=['Verkaufsbezirke', 'II/23'])
print(data_frame)
Hier die Ausgabe des obigen Listings:
Verkaufsbezirke II/23
0 Bezirk A 13500
1 Bezirk B 25100
2 Bezirk C 20000
3 Bezirk D 14900