Zum Inhalt
wannacode

Series und DataFrame

Kurz gesagt: In pandas ist eine Series eine Spalte mit Beschriftungen und ein DataFrame eine Tabelle aus solchen Spalten; der Index trägt die Namen der Zeilen und richtet die Rechnung nach ihnen aus.

Problem

„Wie viel Geld liegt im Lager?“

Der Chef fragt, was der Bestand im Lager wert ist. Die Antwort ist Preis mal Bestand für jedes Produkt, dann eine Summe. Als Nächstes will er die Zahl für ein Produkt sehen, mit Namen.

Mit NumPy kannst du das schon rechnen. Aber in der Lektion über Zusammenfassungen lieferte argmax 22, eine Position, und den Namen musstest du aus einem getrennten Array names holen. Sortierst du das eine Array und vergisst das andere, laufen Namen und Zahlen auseinander, und niemand merkt es.

pandas hält neben jeder Zahl eine Beschriftung: welches Produkt es ist. In dieser Lektion siehst du, wie.

Die Idee

Eine Spalte mit Beschriftungen: Series

Eine Series ist ein NumPy-Array mit einer Beschriftung neben jedem Wert. Die Beschriftungen heißen Index. Hier sind drei Preise mit den Produktnamen als Index:

PythonDaten: die Tabellen des Shops

prices['Weißkäse'] liefert 7.9: Der Wert wird nach Beschriftung genommen, nicht nach Platz. prices.index zeigt die Beschriftungen, und to_numpy() liefert die nackten Zahlen als Array.

Die Idee

Eine Tabelle aus Spalten: DataFrame

Ein DataFrame sind mehrere Series mit einem gemeinsamen Index, nebeneinander. Jede Spalte hat einen Namen und einen eigenen Typ. Im ersten Blick hast du ihn gesehen, jetzt siehst du ihn Stück für Stück:

PythonDaten: die Tabellen des Shops
  • columns sind die Namen der Spalten: 6 davon.
  • index ist ein RangeIndex von 0 bis 24: read_csv nummeriert die Zeilen ab 0, wenn du nichts anderes sagst. Die Spalte id ist etwas anderes und beginnt bei 1.
  • dtypes ist der Typ jeder Spalte. int64 und float64 sind Zahlen, str ist Text.

Sieh es dir an

Eine Spalte ist eine Series

Du nimmst eine Spalte mit ihrem Namen in eckigen Klammern, wie im ersten Blick. Das Ergebnis ist eine Series:

PythonDaten: die Tabellen des Shops

Links steht der Index der Tabelle (0, 1, 2), und unten der Name der Spalte (Name: price) und ihr Typ. Alles, was du mit einer Series tun kannst, kannst du mit jeder Spalte tun.

1. Was ist products['stock']?

Die Idee

Namen im Index: set_index

Die Zahlen 0 bis 24 sagen dem Chef nichts. set_index('name') macht die Spalte name zum Index: Die Produktnamen werden zu den Beschriftungen der Zeilen.

PythonDaten: die Tabellen des Shops

Jetzt ist der Bestand an Kaffee by_name['stock']['Kaffeebohnen']: 15 Packungen. Und das teuerste Produkt ist eine Antwort mit Namen:

  • argmax() liefert weiterhin die Position: 22.
  • idxmax() liefert die Beschriftung des größten Werts: „Messerset“. Es gibt auch idxmin().

Die Beschriftungen wandern mit den Zahlen: Was immer du mit einer Series machst, der Name bleibt neben dem Preis.

Die Idee

Und zurück: reset_index

set_index verändert products nicht, es liefert eine neue Tabelle. Die Spalte name ist jetzt ihr Index, also sind es 5 Spalten statt 6. reset_index() macht den Index wieder zu einer gewöhnlichen Spalte und nummeriert die Zeilen wieder ab 0:

PythonDaten: die Tabellen des Shops

Was in den Index kommt, hängt von der Frage ab. Für „nach Namen“ legst du die Namen dorthin; für eine gewöhnliche Tabelle, die du in eine Datei schreibst, machst du sie wieder zu einer Spalte.

Probier es aus

Das billigste Produkt

Welches Produkt ist das billigste? Lege die Namen in den Index (by_name) und lege in cheapest den Namen des Produkts mit dem kleinsten Preis ab.

PythonDaten: die Tabellen des Shops

Sieh es dir an

Der Index richtet die Rechnung aus

Der Lieferant schickt eine neue Preisliste. Die Produkte sind dieselben, aber in anderer Reihenfolge. Mit NumPy-Arrays würdest du das Erste vom Ersten abziehen und das Zweite vom Zweiten. Mit Series zieht pandas die Werte mit der gleichen Beschriftung ab, wo immer sie stehen:

PythonDaten: die Tabellen des Shops

Bei den Series ist der Kaffee um 1 € gestiegen, das Brot um 0,10 € und der Käse um 0,50 €. Bei den Arrays ist die erste Zahl 13,70 €: der neue Preis des Kaffees minus der alte Preis des Brotes. Die letzte ist -12,30 €: Milch minus Kaffee. Die Zahlen sehen völlig seriös aus, und sie sind falsch.

Das nennt man Ausrichtung am Index. Das Ergebnis ist nach Beschriftung geordnet, alphabetisch.

Sieh es dir an

Eine Beschriftung, die fehlt

Steht eine Beschriftung nur in einer der Series, hat pandas nichts, womit es rechnen kann:

PythonDaten: die Tabellen des Shops

Weißkäse steht nur in dieser Woche, also ist seine Differenz NaN. Das ist ehrlich: Wir wissen nicht, wie viel Käse wir in der letzten Woche verkauft haben. In den Zusammenfassungen hast du gesehen, dass fehlend nicht null ist, und pandas hält sich daran.

Genauer, für Neugierige

Wenn du weißt, dass fehlend null bedeutet (ein Produkt, das wir letzte Woche nicht verkauft haben), sag es ausdrücklich: this_week.sub(last_week, fill_value=0). So ist die Entscheidung im Code sichtbar und nicht versteckt. Die Ausrichtung gilt für +, -, *, / und für Vergleiche zwischen zwei Series.

Probier es aus

Was teurer geworden ist

Die beiden Preislisten haben eine andere Reihenfolge. Lege in change ab, wie sich der Preis jedes Produkts geändert hat (neu minus alt), auf 2 Stellen gerundet, mit den Produktnamen im Index.

PythonDaten: die Tabellen des Shops

Übung

Der Bestand im Lager

Beantworte die Frage des Chefs. Lege die Produktnamen in den Index. Lege in stock_value den Wert des Bestands jedes Produkts ab (Preis mal Bestand), in total seine Summe und in real_total die Summe ohne die Geschenkkarte, auf 2 Stellen gerundet.

PythonDaten: die Tabellen des Shops

Test

Teste dich

1. Die Tabelle products wurde mit read_csv gelesen. Was ist products.index?
2. Was liefern nach by_name = products.set_index('name') die Ausdrücke by_name['price'].argmax() und by_name['price'].idxmax()?
3. Die Woche this_week hat Weißkäse, last_week nicht. Was ist (this_week - last_week)['Weißkäse']?
4. Zwei Preislisten sind Series mit den Produktnamen, aber in verschiedener Reihenfolge. Warum ist new.to_numpy() - old.to_numpy() gefährlich?

Erstellt von Ivo Gergov im Rahmen der Kampagne von Evo Tech für zugängliche Programmierausbildung ·