Zeilen sortieren — und entscheiden, was bei Gleichständen passiert
Zeilen mit sort_values in Reihenfolge bringen: eine Spalte oder mehrere, jede in ihrer eigenen Richtung, fehlende Werte und Text, der wie Zahlen aussieht — plus nlargest für „Top N“ und warum ein Gleichstand an der Grenze eine Entscheidung sein muss, kein Zufall.
Wie möchtest du lernen?
Das Problem, das wir lösen
Die Inhaberin des Geschäfts schickt eine kurze Nachricht: „Was waren diesen Monat unsere größten Bestellungen? Schick mir die besten drei.“
Die Daten stammen aus der vertrauten Datei orders.csv — acht Bestellungen aus den drei Filialen des Geschäfts: Nord, Süd und Ost. Bei acht Zeilen könntest du die Frage mit bloßem Auge beantworten. Schau in die Spalte quantity, finde die 30, dann die 20, dann die 12. Fertig.
Stell dir nun die echte Datei vor: viertausend Bestellungen. Eine Spalte von oben nach unten zu überfliegen, um die drei größten Zahlen zu finden, ist keine Methode mehr, sondern ein reines Hoffen. Und die nächste Nachricht der Inhaberin ist bereits unterwegs: „Kannst du mir die Liste nach Filiale gruppiert schicken, mit der größten zuerst innerhalb jeder Filiale? Und bitte die neuesten Bestellungen ganz oben.“
Jede dieser Anfragen verlangt dieselbe Operation: die Zeilen in eine sinnvolle Reihenfolge bringen und dann von oben her ablesen. Das ist Sortieren, und in pandas ist es eine einzige Methode: sort_values().
Aber die Methode ist der einfache Teil. Die eigentlichen Fragen liegen drumherum, und genau dort entstehen Fehler in Berichten:
- „Größte“ wonach? Menge, Preis oder der Umsatz, den die Bestellung eingebracht hat? Jede Option ergibt andere Top Drei.
- Wenn zwei Bestellungen gleichauf liegen, welche kommt zuerst — und ändert sich die Antwort jedes Mal, wenn du den Code ausführst?
- Was passiert mit einer Bestellung, deren Menge leer ist?
- Wenn eine Zahlenspalte als Text eingelesen wurde, wird
"9"nach"30"einsortiert, und nichts warnt dich davor.
Dieses Kapitel vermittelt die Methode und, was noch wichtiger ist, diese Entscheidungen.
Am Ende dieses Kapitels kannst du
- eine Tabelle mit
sort_values()nach einer oder mehreren Spalten sortieren, jede in ihrer eigenen Richtung, und das Ergebnis behalten, anstatt es zu verlieren - erklären, warum Index-Labels mit ihren Zeilen mitwandern, und zwischen dem Beibehalten der Labels,
sort_index()undreset_index(drop=True)wählen - Gleichstände gezielt auflösen und mit
na_positionentscheiden, wohin fehlende Werte gehören - „Top N“-Fragen mit
head(),nlargest()undnsmallest()beantworten — einschließlich „Top N einer Teilmenge“ und Gleichständen an der Grenze - Text mit
key=unabhängig von Groß- und Kleinschreibung sortieren und als Text gespeicherte Zahlen an ihrer Sortierreihenfolge erkennen
Voraussetzungen: Fehlende Daten — Lücken finden, entfernen und füllen.
Erstelle zuerst die Datei
Jedes Beispiel in diesem Kapitel liest orders.csv ein, dieselbe Datei, die seit Kapitel vier verwendet wird. Falls du sie noch nicht hast, erstelle sie in deinem Projektordner mit genau diesen Zeilen:
order_id,date,branch,product,category,quantity,price
1001,2024-03-01,north,pen,stationery,12,15.0
1002,2024-03-01,south,notebook,stationery,5,60.0
1003,2024-03-02,north,bag,accessories,2,850.0
1004,2024-03-02,east,bottle,accessories,7,120.0
1005,2024-03-03,north,eraser,stationery,30,8.0
1006,2024-03-03,south,bag,accessories,1,850.0
1007,2024-03-04,east,pen,stationery,20,15.0
1008,2024-03-04,north,bottle,accessories,4,120.0Ein späterer Abschnitt verwendet eine zweite Datei, orders_gaps.csv. Es ist dieselbe Tabelle, in der zwei Mengen leer gelassen wurden — die Bestellungen 1002 und 1007 —, genau die Art von Lücke, die du in Kapitel sechs aufzuspüren gelernt hast:
order_id,date,branch,product,category,quantity,price
1001,2024-03-01,north,pen,stationery,12,15.0
1002,2024-03-01,south,notebook,stationery,,60.0
1003,2024-03-02,north,bag,accessories,2,850.0
1004,2024-03-02,east,bottle,accessories,7,120.0
1005,2024-03-03,north,eraser,stationery,30,8.0
1006,2024-03-03,south,bag,accessories,1,850.0
1007,2024-03-04,east,pen,stationery,,15.0
1008,2024-03-04,north,bottle,accessories,4,120.0Bevor du den Code schreibst
Sortieren wirkt zu einfach, als dass man es planen müsste. Das täuscht, denn eine Sortierung schlägt niemals fehl — sie liefert immer eine Reihenfolge. Wenn du nach dem Falschen sortiert hast, sieht das Ergebnis genauso ordentlich aus wie das richtige. Das Nachdenken muss also vor dem Code geschehen.
1. Formuliere die Frage in einem Satz und nenne die Spalte. „Größte Bestellungen“ ist keine Frage, die pandas beantworten kann. „Die drei Bestellungen mit der größten quantity“ hingegen schon. Ebenso „die drei Bestellungen mit dem höchsten price“. Sie liefern unterschiedliche Antworten — die Tasche für 850 ist der teuerste Artikel, aber es wurden nur zwei Taschen verkauft. Entscheide, was die Inhaberin meint. Wenn du es nicht weißt, frag nach; das kostet eine Nachricht, und falsche Top Drei kosten Vertrauen.
2. Sieh dir die Eingabedaten an, bevor du sortierst. Drei Dinge spielen beim Sortieren eine Rolle: die Anzahl der Zeilen, die Typen der Spalten, nach denen du sortieren willst, und ob diese Spalten Lücken aufweisen.
import pandas as pd
orders = pd.read_csv("orders.csv")
print(orders.shape)
print(orders.dtypes)
print(orders["quantity"].isna().sum())(8, 7)
order_id int64
date str
branch str
product str
category str
quantity int64
price float64
dtype: object
0Acht Zeilen, sieben Spalten. quantity ist int64 und price ist float64, sie werden also als Zahlen sortiert. branch und product sind str — Text, der alphabetisch sortiert wird. date ist ebenfalls str. Das ist hier kein Problem, und der Grund dafür ist wissenswert: Datumsangaben im Format YYYY-MM-DD werden auch als Text korrekt sortiert, weil der signifikanteste Teil zuerst kommt. Datumsangaben im Format 4/3/2024 würden das nicht. Und quantity hat keine Lücken, wir müssen also noch nicht entscheiden, wohin fehlende Werte gehören — jedenfalls jetzt noch nicht.
3. Skizziere die Ausgabe. Für „Top Drei nach Menge“ sollte das Ergebnis aus drei Zeilen bestehen, die größte zuerst: 30 (Radiergummi, Bestellung 1005), dann 20 (Stift, 1007), dann 12 (Stift, 1001). Wenn du das aufschreibst, bevor du etwas ausführst, hast du einen Anhaltspunkt, um den Code zu überprüfen.
4. Entscheide über die Details, die eine Sortierung benötigt.
- Schlüssel (Key) — welche Spalte oder Spalten bestimmen die Reihenfolge? Das wird zu
by=. - Richtung — kleinste zuerst oder größte zuerst, für jeden Schlüssel? Das wird zu
ascending=. - Gleichstände (Ties) — wenn zwei Zeilen denselben Wert haben, welche kommt zuerst? Das wird zu einem zweiten Schlüssel oder
kind="stable". - Lücken — sollen fehlende Werte an den Anfang oder ans Ende? Das wird zu
na_position=. - Wie viele — alle Zeilen oder nur die oberen N? Das wird zu
.head(n)odernlargest(). - Index — bedeuten die alten Zeilen-Labels danach noch etwas? Behalte sie, oder verwirf sie mit
reset_index(drop=True).
5. Wähle das Werkzeug aus.
- Jede Zeile, in der Reihenfolge einer oder mehrerer Spalten:
sort_values() - Nur die obersten oder untersten N nach einer numerischen Spalte:
nlargest()/nsmallest() - Die Zeilen zurück in Index-Reihenfolge:
sort_index() - Die oberen N innerhalb einer Teilmenge („in der Nordfiliale“): erst filtern, dann sortieren, dann
head()
6. Wisse, wie du das Ergebnis überprüfst. Nach dem Sortieren sollten die ersten Zeilen mit deiner Skizze übereinstimmen, shape sollte unverändert sein (eine Sortierung fügt niemals Zeilen hinzu oder entfernt welche), und bei einem numerischen Schlüssel sollte die Spalte auf der Seite monoton verlaufen.
sort_values() — eine Spalte
Um die Ausgaben schmal zu halten, zeigen die Beispiele fünf der sieben Spalten. cols ist einfach eine Liste von Namen, die mit der Auswahl über doppelte eckige Klammern aus Kapitel vier verwendet wird.
cols = ["order_id", "branch", "product", "quantity", "price"]
by_qty = orders.sort_values("quantity")
print(by_qty[cols])order_id branch product quantity price
5 1006 south bag 1 850.0
2 1003 north bag 2 850.0
7 1008 north bottle 4 120.0
1 1002 south notebook 5 60.0
3 1004 east bottle 7 120.0
0 1001 north pen 12 15.0
6 1007 east pen 20 15.0
4 1005 north eraser 30 8.0Der Standard ist aufsteigend (ascending) — kleinste zuerst. Lies die Spalte quantity von oben nach unten: 1, 2, 4, 5, 7, 12, 20, 30. Das ist die Überprüfung aus dem Plan: Ein numerischer Schlüssel sollte immer nur ansteigen.
Schau dir nun den linken Rand an. Der Index lautet nicht mehr 0, 1, 2, …. Er lautet 5, 2, 7, 1, 3, 0, 6, 4.
Warum der Index mit der Zeile mitwandert
Pandas hat die Zeilen nicht neu nummeriert, und das ist Absicht. Ein Index-Label ist der Name der Zeile, nicht ihre Position. Label 5 war vor der Sortierung Bestellung 1006 und ist es auch nach der Sortierung noch. Würde das Sortieren die Zeilen neu nummerieren, würde jedes Label plötzlich auf eine andere Bestellung zeigen, und jede Notiz, die du dir zu „Zeile 5“ gemacht hast, wäre stillschweigend falsch.
Nach einer Sortierung gibt es also zwei verschiedene Arten, „die erste Zeile“ zu bezeichnen, und sie stimmen nicht mehr überein:
print(by_qty.iloc[0]["order_id"])
print(by_qty.loc[0]["order_id"])1006
1001iloc[0] bedeutet Position Null — die erste Zeile auf der Seite, Bestellung 1006. loc[0] bedeutet die Zeile mit dem Label 0 — Bestellung 1001, die nun an sechster Stelle auf der Seite steht. In Kapitel vier wurde dieser Unterschied herausgearbeitet; das Sortieren ist die Operation, die ihm Bedeutung verleiht. Wenn du „die oberste Zeile nach dem Sortieren“ haben möchtest, verwende iloc oder head(), die beide Positionen zählen.
Größte zuerst: ascending=False
print(orders.sort_values("quantity", ascending=False)[cols])order_id branch product quantity price
4 1005 north eraser 30 8.0
6 1007 east pen 20 15.0
0 1001 north pen 12 15.0
3 1004 east bottle 7 120.0
1 1002 south notebook 5 60.0
7 1008 north bottle 4 120.0
2 1003 north bag 2 850.0
5 1006 south bag 1 850.0Die ersten drei sind 1005, 1007 und 1001 — exakt die Skizze aus dem Plan. Um nur diese drei zu verschicken, hänge head(3) an:
top3 = orders.sort_values("quantity", ascending=False).head(3)
print(top3[cols])order_id branch product quantity price
4 1005 north eraser 30 8.0
6 1007 east pen 20 15.0
0 1001 north pen 12 15.0Liest man den Methodenaufruf von links nach rechts, spiegelt er genau den Plan wider: Nimm orders, setze die größte Menge an die Spitze, behalte die ersten drei. Dieses Muster „erst sortieren, dann head“ beantwortet die meisten „Top N“-Fragen.
Text wird alphabetisch sortiert
Eine str-Spalte wird in lexikografischer Reihenfolge sortiert:
print(orders.sort_values("product")[cols])order_id branch product quantity price
2 1003 north bag 2 850.0
5 1006 south bag 1 850.0
3 1004 east bottle 7 120.0
7 1008 north bottle 4 120.0
4 1005 north eraser 30 8.0
1 1002 south notebook 5 60.0
0 1001 north pen 12 15.0
6 1007 east pen 20 15.0bag vor bottle, weil a vor o kommt. Zwei Taschen, zwei Flaschen und zwei Stifte — das sind Gleichstände (Ties), und wir kommen gleich auf die Frage zurück, welches von zwei gleichrangigen Elementen zuerst kommt.
Eine Sortierung gibt eine neue Tabelle zurück
Das ist der Fehler, den fast jeder einmal macht, und er löst keinen Fehler aus:
orders.sort_values("quantity", ascending=False)
print(orders[cols].head(3))order_id branch product quantity price
0 1001 north pen 12 15.0
1 1002 south notebook 5 60.0
2 1003 north bag 2 850.0Nichts ist sortiert. sort_values() verändert orders nicht; es erstellt und liefert ein neues DataFrame in der neuen Reihenfolge. Die erste Zeile hat diese sortierte Tabelle erstellt und — da niemand sie gespeichert hat — wieder verworfen. orders ist exakt das, was read_csv erzeugt hat.
Warum arbeitet pandas so? Weil auch die ursprüngliche Reihenfolge eine Information ist. In orders.csv ist es die Reihenfolge, in der die Bestellungen eingegangen sind. Wenn jede Sortierung deine einzige Kopie umräumen würde, könntest du niemals mehr zum Zustand „wie die Datei war“ zurückkehren, und eine für einen Bericht geschriebene Sortierung würde stillschweigend die Eingabe des nächsten Berichts verändern. Die Rückgabe eines neuen Objekts bedeutet, dass das Sortieren immer gefahrlos ausprobiert werden kann.
sort_values() ändert niemals die Tabelle, auf der du es aufrufst. Wenn du das Ergebnis nicht zuweist, wurde die Sortierung zwar ausgeführt, aber sofort verworfen — und nichts warnt dich davor.Du behältst das Ergebnis also, entweder unter einem neuen Namen oder indem du es demselben Namen wieder zuweist:
by_qty_desc = orders.sort_values("quantity", ascending=False) # keep both
print(by_qty_desc["order_id"].head(3).tolist())
print(orders["order_id"].head(3).tolist())[1005, 1007, 1001]
[1001, 1002, 1003]Die sortierte Kopie hat die großen Bestellungen ganz oben; das Original ist unberührt. orders = orders.sort_values(...) zu schreiben ist ebenfalls völlig in Ordnung, wenn du sicher bist, dass du die alte Reihenfolge nicht mehr brauchst.
In älterem Code wirst du inplace=True sehen. Es ändert die Tabelle an Ort und Stelle und gibt None zurück, was zu einem ganz eigenen Fehler führt (siehe Wenn etwas schiefgeht). Mit Copy-on-Write in pandas 3 spart inplace=True auch keinen Speicherplatz mehr. Das Zuweisen des Ergebnisses ist klarer: Man sieht direkt in der Zeile, wohin die sortierte Tabelle fließt.
Mehrere Spalten: Priorität und Richtung
Die zweite Bitte der Inhaberin: „nach Filiale gruppiert, mit der größten zuerst innerhalb jeder Filiale.“ Das sind zwei Schlüssel, und die Reihenfolge der Liste bestimmt die Priorität:
by_branch = orders.sort_values(["branch", "quantity"], ascending=[True, False])
print(by_branch[cols])order_id branch product quantity price
6 1007 east pen 20 15.0
3 1004 east bottle 7 120.0
4 1005 north eraser 30 8.0
0 1001 north pen 12 15.0
7 1008 north bottle 4 120.0
2 1003 north bag 2 850.0
1 1002 south notebook 5 60.0
5 1006 south bag 1 850.0Lies es so, wie pandas es aufgebaut hat. Zuerst wird jede Zeile nach branch von A bis Z platziert: east, north, south. Der zweite Schlüssel, quantity, wird erst herangezogen, wenn beim ersten Schlüssel Gleichstand herrscht — innerhalb von east, innerhalb von north, innerhalb von south. Innerhalb von north lautet die Reihe 30, 12, 4, 2: die größte zuerst, weil der zweite Eintrag von ascending auf False steht.
ascending nimmt ein True/False pro Schlüssel entgegen, in derselben Reihenfolge wie by. Ein einzelnes False würde für beide Schlüssel gelten und south an die erste Stelle setzen.
Das Vertauschen der Liste ändert die Fragestellung grundlegend:
print(orders.sort_values(["quantity", "branch"], ascending=[False, True])[cols].head(4))order_id branch product quantity price
4 1005 north eraser 30 8.0
6 1007 east pen 20 15.0
0 1001 north pen 12 15.0
3 1004 east bottle 7 120.0Jetzt gibt die Menge den Ton an, und branch würde nur dann eine Rolle spielen, wenn zwei Bestellungen dieselbe Menge hätten — was bei keiner der Fall ist. Die Filialen sind wild verstreut. Die Frage, die man sich vor dem Schreiben der Liste stellen muss, lautet also: „Wonach ist der Bericht gegliedert?“ Diese Spalte kommt an die erste Stelle.
Gleichstände: Mach die Reihenfolge zu einer Entscheidung, nicht zum Zufall
Sortiere nach price, das teuerste zuerst:
print(orders.sort_values("price", ascending=False)[cols])order_id branch product quantity price
2 1003 north bag 2 850.0
5 1006 south bag 1 850.0
7 1008 north bottle 4 120.0
3 1004 east bottle 7 120.0
1 1002 south notebook 5 60.0
0 1001 north pen 12 15.0
6 1007 east pen 20 15.0
4 1005 north eraser 30 8.0Sieh dir die beiden Flaschen zu 120 an. In der Datei kommt Bestellung 1004 vor 1008. In der sortierten Tabelle steht 1008 an erster Stelle. Es ist nichts kaputt: Bei einem einzelnen Schlüssel garantiert der Standard-Sortieralgorithmus von pandas (quicksort) nicht, dass gleichrangige Zeilen in ihrer ursprünglichen Reihenfolge bleiben — und hier blieben sie es nicht. Die beiden Taschen zu 850 blieben in der Reihenfolge der Datei, die beiden Flaschen wurden vertauscht — es gab keine Regel, die du hättest vorhersagen können.
Meistens spielt das keine Rolle. Es beginnt genau in dem Moment eine Rolle zu spielen, in dem du die Liste abschneidest. Wenn der Bericht „die drei teuersten Bestellungen“ verlangt, ist der dritte Platz ein Gleichstand zwischen 1004 und 1008 — und welche davon auf der Liste landet, hat der Algorithmus entschieden, nicht du. Führe denselben Code auf einer leicht veränderten Datei aus, und das Ergebnis kann sich ändern.
Es gibt zwei Wege, diese Entscheidung selbst in die Hand zu nehmen.
Option 1: eine stabile Sortierung. kind="stable" garantiert, dass gleichrangige Zeilen die Reihenfolge behalten, die sie vor der Sortierung hatten — hier die Dateireihenfolge:
stable = orders.sort_values("price", ascending=False, kind="stable")
print(stable["order_id"].tolist())[1003, 1006, 1004, 1008, 1002, 1001, 1007, 1005]Option 2 (meistens besser): ein expliziter Tie-Breaker. Lege fest, was bei Gleichstand gewinnen soll. Für einen Verkaufsbericht ist „wenn der Preis gleich ist, die größere Bestellung zuerst“ eine vernünftige Regel:
tie_broken = orders.sort_values(["price", "quantity"], ascending=[False, False])
print(tie_broken[cols])order_id branch product quantity price
2 1003 north bag 2 850.0
5 1006 south bag 1 850.0
3 1004 east bottle 7 120.0
7 1008 north bottle 4 120.0
1 1002 south notebook 5 60.0
6 1007 east pen 20 15.0
0 1001 north pen 12 15.0
4 1005 north eraser 30 8.0Sieh dir die Flaschen noch einmal an: 1004 steht über 1008, weil 7 mehr ist als 4. Und die beiden Stifte zu 15: Vorher kam 1001 zuerst; jetzt gewinnt 1007, weil 20 mehr ist als 12 — und sie gewinnt jedes Mal, auf jedem Rechner, ganz egal, in welcher Reihenfolge die Datei ankommt. Ein Tie-Breaker macht aus einem Zufall eine Regel, die du der Inhaberin erklären kannst. (Wenn du nach mehr als einer Spalte sortierst, ist die Sortierung in pandas ohnehin stabil, sodass eine Liste von Schlüsseln echte Gleichstände ebenfalls niemals durcheinanderbringt.)
Wenn du keine fachliche Geschäftsregel hast, eignet sich order_id hervorragend als letzter Schlüssel: Sie ist eindeutig, sodass nach ihr überhaupt keine Gleichstände mehr übrig bleiben.
Fehlende Werte: na_position
Lies die Version der Datei mit zwei leeren Mengen ein:
gaps = pd.read_csv("orders_gaps.csv")
print(gaps["quantity"].isna().sum())
print(gaps.sort_values("quantity", ascending=False)[cols])2
order_id branch product quantity price
4 1005 north eraser 30.0 8.0
0 1001 north pen 12.0 15.0
3 1004 east bottle 7.0 120.0
7 1008 north bottle 4.0 120.0
2 1003 north bag 2.0 850.0
5 1006 south bag 1.0 850.0
1 1002 south notebook NaN 60.0
6 1007 east pen NaN 15.0Zwei Dinge fallen auf. Erstens wird quantity jetzt als 30.0, 12.0 ausgegeben — die Lücken haben die Spalte in float64 verwandelt, wie in Kapitel sechs erklärt, weil NaN ein Float ist. Zweitens sind die NaN-Zeilen ganz nach unten gewandert, obwohl wir nach der größten zuerst gefragt hatten. Das ist der Standard, na_position="last", und er gilt in beide Richtungen: Ein fehlender Wert ist weder „klein“ noch „groß“, sondern unbekannt, also legt pandas ihn beiseite, anstatt zu raten.
Beachte, was das mit den Top Drei gemacht hat. Bei Bestellung 1007 wurden tatsächlich 20 Stifte verkauft, aber ihre Menge ist in dieser Datei leer, sodass sie aus den Top Drei herausgefallen ist und 1004 ihren Platz eingenommen hat. Eine Sortierung kann fehlende Daten nicht reparieren; sie kann dir nur zeigen, wohin die Lücken gewandert sind. Deshalb zählt Schritt 2 des Plans Lücken vor dem Sortieren.
Wenn du die Daten prüfst, möchtest du oft das Gegenteil — die Probleme ganz oben, wo du sie direkt siehst:
print(gaps.sort_values("quantity", na_position="first")[cols].head(3))order_id branch product quantity price
1 1002 south notebook NaN 60.0
6 1007 east pen NaN 15.0
5 1006 south bag 1.0 850.0na_position ist also keine bloße Formatierungsentscheidung. "last" eignet sich für einen Bericht, in dem Lücken echte Werte nicht verdrängen sollen. "first" eignet sich für eine Prüfung, bei der Lücken genau das sind, wonach du suchst.
Zurück zum Anfang: sort_index() und reset_index()
Da jede Zeile ihr Label behalten hat, geht die ursprüngliche Reihenfolge niemals verloren. Ein Sortieren nach dem Index bringt sie wieder zurück:
restored = by_qty.sort_index()
print(restored["order_id"].tolist())[1001, 1002, 1003, 1004, 1005, 1006, 1007, 1008]sort_index() akzeptiert ebenfalls ascending=False, womit du eine Tabelle nach dem Schema „neuestes Label zuerst“ auflisten würdest.
Manchmal haben die alten Labels ihre Bedeutung verloren. Wenn du sortierst, um eine Rangliste zu erstellen und weiterzuschicken, stiften die Labels 4, 6, 0 am Rand nur Verwirrung. reset_index(drop=True) verwirft sie und nummeriert die Zeilen in ihrer neuen Reihenfolge mit 0, 1, 2, …:
ranked = orders.sort_values("quantity", ascending=False).reset_index(drop=True)
print(ranked[cols].head(3))
print(ranked.loc[0, "order_id"])order_id branch product quantity price
0 1005 north eraser 30 8.0
1 1007 east pen 20 15.0
2 1001 north pen 12 15.0
1005Jetzt stimmen loc[0] und iloc[0] wieder überein: Beide sind Bestellung 1005, die größte. Ohne drop=True würde pandas die alten Labels als neue Spalte namens index behalten — nützlich, wenn du Zeilen zum Ursprung zurückverfolgen willst, überflüssiger Ballast, wenn nicht.
Wann wählt man was? Behalte die Labels, solange du noch mit den Daten arbeitest und Zeilen eventuell mit dem Original abgleichen musst. Setze sie zurück, wenn die Reihenfolge selbst das Ergebnis ist — eine Rangliste, eine Top-Ten-Liste.
Die Abkürzung für „Top N“: nlargest() und nsmallest()
„Top Drei nach Menge“ kommt so häufig vor, dass pandas eine Methode bietet, die genau das aussagt:
print(orders.nlargest(3, "quantity")[cols])order_id branch product quantity price
4 1005 north eraser 30 8.0
6 1007 east pen 20 15.0
0 1001 north pen 12 15.0Dieselben Zeilen wie bei sort_values("quantity", ascending=False).head(3). Warum sollte man sie vorziehen? Die Zeile drückt die Absicht aus — „die drei größten“ — statt den Mechanismus. Und bei einer großen Tabelle ist sie schneller, weil sie nicht erst alle Zeilen sortieren muss, nur um drei davon zu behalten.
nsmallest() ist das genaue Spiegelbild: die drei günstigsten Artikel im Geschäft:
print(orders.nsmallest(3, "price")[cols])order_id branch product quantity price
4 1005 north eraser 30 8.0
0 1001 north pen 12 15.0
6 1007 east pen 20 15.0Gleichstände an der Grenze: keep=
Fragt man nach den drei teuersten Artikeln, passiert etwas Heikles:
print(orders.nlargest(3, "price")[cols])order_id branch product quantity price
2 1003 north bag 2 850.0
5 1006 south bag 1 850.0
3 1004 east bottle 7 120.0Der dritte Platz liegt bei 120 — aber zwei Bestellungen kosten 120: 1004 und 1008. pandas hat eine davon zurückgegeben — mit dem Standardwert keep="first" jene, die in der Tabelle zuerst auftaucht — und die andere stillschweigend weggelassen. Wenn du einen Preis an „die besten drei“ verleihst, ist das ungerecht gegenüber 1008. keep="all" behält jede Zeile, die an der Grenze gleichauf liegt, selbst wenn das mehr als N Zeilen bedeutet:
print(orders.nlargest(3, "price", keep="all")[cols])order_id branch product quantity price
2 1003 north bag 2 850.0
5 1006 south bag 1 850.0
3 1004 east bottle 7 120.0
7 1008 north bottle 4 120.0Vier Zeilen für „Top Drei“. Das ist kein Fehler: Es ist die ehrliche Antwort, wenn der dritte Platz geteilt wird. Ob du das möchtest, ist wiederum eine Planungsentscheidung.
nlargest und nsmallest funktionieren nur bei numerischen Spalten. Bei Text verwendest du sort_values und head.
Top N einer Teilmenge: erst filtern, dann sortieren, dann abschneiden
„Was waren die zwei größten Bestellungen in der Nordfiliale?“ Dies verbindet Kapitel fünf mit diesem Kapitel, und die Reihenfolge der Schritte ist entscheidend:
north = orders[orders["branch"] == "north"]
top_north = north.sort_values("quantity", ascending=False).head(2)
print(top_north[cols])order_id branch product quantity price
4 1005 north eraser 30 8.0
0 1001 north pen 12 15.0Filtere zuerst, denn die Frage bezieht sich ausschließlich auf die Nordfiliale. Würdest du die gesamte Tabelle sortieren und zuerst head(2) nehmen, erhieltest du 1005 und 1007 — und 1007 gehört zur Ostfiliale. Das nachträgliche Filtern würde dann nur eine einzige Zeile übrig lassen, und du würdest „Top Zwei“ mit einem einzelnen Eintrag melden. Die Regel lautet: Grenze auf die Zeilen ein, um die es in der Frage geht, bringe sie in Rangfolge und schneide dann ab.
Dieselbe Kette funktioniert auch mit nlargest: orders[orders["branch"] == "north"].nlargest(2, "quantity").
Text ohne Rücksicht auf Groß-/Kleinschreibung sortieren: key=
Beim Sortieren von Text werden Zeichen anhand ihres Zeichencodes verglichen, und jeder Großbuchstabe kommt vor jedem Kleinbuchstaben. Von Menschen eingegebene Daten mischen oft beides:
names = pd.DataFrame({"product": ["pen", "Notebook", "bag", "Bottle", "eraser"]})
print(names.sort_values("product"))product
3 Bottle
1 Notebook
2 bag
4 eraser
0 penBottle und Notebook springen vor bag, einfach nur, weil sie mit einem Großbuchstaben beginnen. Kein Leser würde das als alphabetisch bezeichnen.
Du könntest die Daten bereinigen, aber oft solltest du das nicht — die Schreibweise ist vielleicht genau die, die der Kunde eingegeben hat. Das Argument key= ermöglicht es dir, nach einer transformierten Version der Spalte zu sortieren, während die ursprünglichen Werte erhalten bleiben. Es nimmt eine Funktion entgegen, die die gesamte Spalte erhält und die Version zurückgibt, nach der sortiert werden soll:
print(names.sort_values("product", key=lambda col: col.str.lower()))product
2 bag
3 Bottle
4 eraser
1 Notebook
0 penDie kleingeschriebene Kopie wird nur für den Vergleich verwendet und danach verworfen. Die Tabelle zeigt Bottle und Notebook weiterhin exakt so, wie sie eingegeben wurden. (lambda col: col.str.lower() ist eine einzeilige Funktion: Nimm die Spalte col und gib sie in Kleinbuchstaben zurück.)
Wenn Zahlen als Text gespeichert sind
Hier ist die Falle, die der Planungsschritt zu dtypes aufdecken soll. Angenommen, quantity kam als Text an — durch ein verirrtes "N/A" in der Datei oder ein System, das alles als Strings exportiert. Um zu sehen, was das bewirkt, erzeugen wir eine solche Spalte absichtlich mit astype:
as_text = orders.astype({"quantity": "str"})
print(as_text["quantity"].dtype)
print(as_text.sort_values("quantity")[["order_id", "quantity"]])str
order_id quantity
5 1006 1
0 1001 12
2 1003 2
6 1007 20
4 1005 30
7 1008 4
1 1002 5
3 1004 71, 12, 2, 20, 30, 4, 5, 7. Kein Fehler und eine Reihenfolge, die fast richtig aussieht. Text wird Zeichen für Zeichen verglichen: "12" beginnt mit 1, was kleiner als 2 ist, daher kommt "12" vor "2" — genauso wie „ab“ im Wörterbuch vor „b“ steht. Die Sortierung tat genau das, was ihr aufgetragen wurde. Ihr wurde nur das Falsche aufgetragen.
Zwei Hinweise verraten es: quantity ist in der Ausgabe linksbündig ausgerichtet, so wie pandas Text ausgibt, und dtype meldet str. Die eigentliche Lösung besteht darin, die Spalte in Zahlen umzuwandeln (das pd.to_numeric aus Kapitel sechs). Wenn du die Spalte so belassen musst, wie sie ist, kann key= stattdessen nach dem numerischen Wert sortieren:
fixed = as_text.sort_values("quantity", key=pd.to_numeric)
print(fixed["quantity"].tolist())['1', '2', '4', '5', '7', '12', '20', '30']Jetzt stimmt die Reihenfolge — aber die Werte sind immer noch Strings, du könntest sie also nicht summieren. Konvertiere die Spalte besser einmal direkt nach dem Einlesen der Datei. Dann ist jede nachfolgende Sortierung, Filterung und Summe korrekt, ohne dass du jedes Mal daran denken musst.
Ein vollständiges Beispiel
Die vollständige Anfrage der Inhaberin, beantwortet in einem einzigen Programm: (1) die Top Drei der Bestellungen nach erzieltem Umsatz, (2) die neuesten Bestellungen zuerst, (3) eine Liste nach Filialen mit der größten Bestellung zuerst in jeder Filiale.
„Erzielter Umsatz“ ist Menge mal Preis. Das Hinzufügen von Spalten wird später im Kurs ausführlich behandelt; fürs Erste genügt eine einzige Zeile — die Zuweisung an einen neuen Spaltennamen erstellt sie.
sorted_report.py:
import pandas as pd
orders = pd.read_csv("orders.csv")
# Check the input before ranking anything
print("Rows, columns:", orders.shape)
print("Blank quantities:", orders["quantity"].isna().sum())
print()
orders["revenue"] = orders["quantity"] * orders["price"]
cols = ["order_id", "date", "branch", "product", "revenue"]
# 1. Top three by revenue, ties broken by the larger quantity, renumbered as a ranking
top3 = (
orders.sort_values(["revenue", "quantity"], ascending=[False, False])
.head(3)
.reset_index(drop=True)
)
print("Top three orders by revenue")
print(top3[cols])
print()
# 2. Newest first; within the same day, the bigger order first
newest = orders.sort_values(["date", "revenue"], ascending=[False, False])
print("Newest first")
print(newest[cols].head(4))
print()
# 3. By branch A-Z, biggest order first inside each branch
by_branch = orders.sort_values(["branch", "revenue"], ascending=[True, False])
print("By branch")
print(by_branch[cols])
print()
print("Still eight rows:", by_branch.shape[0] == orders.shape[0])Rows, columns: (8, 7)
Blank quantities: 0
Top three orders by revenue
order_id date branch product revenue
0 1003 2024-03-02 north bag 1700.0
1 1006 2024-03-03 south bag 850.0
2 1004 2024-03-02 east bottle 840.0
Newest first
order_id date branch product revenue
7 1008 2024-03-04 north bottle 480.0
6 1007 2024-03-04 east pen 300.0
5 1006 2024-03-03 south bag 850.0
4 1005 2024-03-03 north eraser 240.0
By branch
order_id date branch product revenue
3 1004 2024-03-02 east bottle 840.0
6 1007 2024-03-04 east pen 300.0
2 1003 2024-03-02 north bag 1700.0
7 1008 2024-03-04 north bottle 480.0
4 1005 2024-03-03 north eraser 240.0
0 1001 2024-03-01 north pen 180.0
5 1006 2024-03-03 south bag 850.0
1 1002 2024-03-01 south notebook 300.0
Still eight rows: TrueWarum es so geschrieben ist:
- Die Überprüfung kommt zuerst.
shapeund die Anzahl der Lücken werden vor jeder Rangordnung ausgegeben. Top Drei, die aus einer unvollständig eingelesenen Datei oder mit ans Ende geschobenen Lücken berechnet wurden, würden genauso überzeugend aussehen. - „Größte“ wurde in eine Spalte verwandelt. Ein Ranking nach
quantitywürde die 30 Radiergummis an die Spitze setzen — ein Warenwert von 240. Ein Ranking nachrevenuesetzt die beiden Taschen im Wert von 1.700 an die Spitze. Der erste Schritt des Plans — formuliere die Frage mit der Spalte darin — entscheidet darüber, welche Antwort die Inhaberin erhält. - Jede Sortierung hat einen Tie-Breaker. Am 2024-03-04 gibt es zwei Bestellungen;
revenueentscheidet, welche zuerst aufgeführt wird, sodass der Bericht bei jedem Durchlauf identisch ist. - Nur die Rangliste wird neu nummeriert.
top3ist eine fertige Liste, daher werden ihre Labels zu 0, 1, 2.newestundby_branchbehalten ihre ursprünglichen Labels, sodass jede Zeile weiterhin zur Datei zurückverfolgt werden kann. ordersselbst wird niemals neu sortiert. Jeder Bericht ist eine neue Tabelle, die aus derselben unberührten Eingabe erstellt wird, sodass sich die drei Antworten nicht gegenseitig beeinflussen können.- Die letzte Zeile ist eine kostengünstige Assertion. Eine Sortierung darf niemals die Anzahl der Zeilen verändern. Die Ausgabe von
Truekostet nichts und würde beispielsweise ein versehentliches, an falscher Stelle verbliebeneshead()aufdecken.
Wenn etwas schiefgeht
KeyError: 'Quantity'
orders.sort_values("Quantity")KeyError: 'Quantity'Der Name in by= muss exakt mit einer Spalte übereinstimmen — Groß-/Kleinschreibung, Leerzeichen und alles andere. Die Spalte heißt quantity, in Kleinbuchstaben. Gib list(orders.columns) aus, um die tatsächlichen Namen inklusive Anführungszeichen und etwaiger überflüssiger Leerzeichen zu sehen, wie in Kapitel drei empfohlen.
AttributeError: 'NoneType' object has no attribute 'head'
top = orders.sort_values("quantity", inplace=True)
top.head()AttributeError: 'NoneType' object has no attribute 'head'Mit inplace=True ändert sort_values das DataFrame orders und gibt None zurück. top ist also None, und None besitzt kein head(). Wähle einen der beiden Stile: entweder orders.sort_values("quantity", inplace=True) in einer eigenen Zeile oder — noch besser — top = orders.sort_values("quantity") ohne inplace.
ValueError: Length of ascending (1) != length of by (2)
orders.sort_values(["branch", "quantity"], ascending=[False])ValueError: Length of ascending (1) != length of by (2)Eine Liste für ascending benötigt einen Eintrag pro Schlüssel. Zwei Schlüssel, zwei Booleans: ascending=[True, False]. (Ein einzelnes einfaches False, nicht in einer Liste, ist erlaubt — es gilt dann für jeden Schlüssel.)
ValueError: For argument "ascending" expected type bool, received type str.
orders.sort_values("branch", ascending="False")ValueError: For argument "ascending" expected type bool, received type str."False" in Anführungszeichen ist ein String, nicht der boolesche Wert False. Entferne die Anführungszeichen.
TypeError: Column 'branch' has dtype str, cannot use method 'nlargest' with this dtype
orders.nlargest(3, "branch")TypeError: Column 'branch' has dtype str, cannot use method 'nlargest' with this dtypenlargest und nsmallest bringen nur Zahlen in eine Rangfolge. Für „die letzten drei Filialen alphabetisch“ verwende orders.sort_values("branch", ascending=False).head(3). Wenn du diesen Fehler bei einer Spalte erhältst, von der du erwartet hast, dass sie numerisch ist, liegt das eigentliche Problem darin, dass sie als Text eingelesen wurde — überprüfe dtypes.
TypeError: '<' not supported between instances of 'str' and 'int'
mixed = pd.Series([12, "unknown", 5])
mixed.sort_values()TypeError: '<' not supported between instances of 'str' and 'int'Diese Spalte enthält echte Zahlen und ein Stück Text, ihr dtype ist also object, und Python kann nicht entscheiden, ob "unknown" größer oder kleiner als 12 ist. Bereinige die Spalte zuerst: pd.to_numeric(mixed, errors="coerce") wandelt "unknown" in NaN um, und danach funktioniert die Sortierung und na_position entscheidet, wohin die Lücke wandert.
Schritt 4 von 6 — Vorhersagen
Prüfe dein Verständnis
Zwei Taschen teilen sich den Höchstpreis von 850.0. Was wird ausgegeben?
from io import StringIO
import pandas as pd
# Stands in for orders.csv, so this snippet runs on its own.
RAW = """order_id,date,branch,product,category,quantity,price
1001,2024-03-01,north,pen,stationery,12,15.0
1002,2024-03-01,south,notebook,stationery,5,60.0
1003,2024-03-02,north,bag,accessories,2,850.0
1004,2024-03-02,east,bottle,accessories,7,120.0
1005,2024-03-03,north,eraser,stationery,30,8.0
1006,2024-03-03,south,bag,accessories,1,850.0
1007,2024-03-04,east,pen,stationery,20,15.0
1008,2024-03-04,north,bottle,accessories,4,120.0
"""
orders = pd.read_csv(StringIO(RAW))
top = orders.sort_values("price", ascending=False)
print(list(top.index[:3]))- A[2, 5, 7]
- B[0, 1, 2]
- C[2, 5, 3]
- D[5, 2, 7]
Das Ziel ist es, die Bestellung mit den meisten Artikeln auszugeben. Was wird ausgegeben?
from io import StringIO
import pandas as pd
# Stands in for orders.csv, so this snippet runs on its own.
RAW = """order_id,date,branch,product,category,quantity,price
1001,2024-03-01,north,pen,stationery,12,15.0
1002,2024-03-01,south,notebook,stationery,5,60.0
1003,2024-03-02,north,bag,accessories,2,850.0
1004,2024-03-02,east,bottle,accessories,7,120.0
1005,2024-03-03,north,eraser,stationery,30,8.0
1006,2024-03-03,south,bag,accessories,1,850.0
1007,2024-03-04,east,pen,stationery,20,15.0
1008,2024-03-04,north,bottle,accessories,4,120.0
"""
orders = pd.read_csv(StringIO(RAW))
orders.sort_values("quantity", ascending=False)
print(orders.iloc[0]["order_id"])- A1001 — `sort_values` hat eine sortierte Kopie zurückgegeben und niemand hat sie behalten
- B1007
- CEin `TypeError`: Das Ergebnis muss zugewiesen werden
- D1005
Du möchtest die Bestellungen nach Filiale von A bis Z gruppiert haben, und innerhalb jeder Filiale die größte Menge zuerst. Welche Zeile tut das?
- Aorders.sort_values("branch").sort_values("quantity", ascending=False)
- Borders.sort_values(["branch", "quantity"], ascending=False)
- Corders.sort_values(["quantity", "branch"], ascending=[False, True])
- Dorders.sort_values(["branch", "quantity"], ascending=[True, False])
Zum Antworten brauchst du ein Konto
Melde dich an, um deine Antworten zu prüfen
Die Fragen stehen oben, und sie im Kopf durchzuarbeiten ist der wichtige Teil. Melde dich an, um die Antworten, die Erklärungen und die dreistufigen Hinweise zu sehen.
Jetzt bist du dran
Eine Lehrkraft schickt dir die Noten einer Prüfung. Speichere dies als results.csv. Zwei Schüler haben noch keine Note, und einige Namen wurden in Kleinbuchstaben eingegeben:
name,section,marks
Rafi,B,78
anika,A,91
Tanvir,A,
Mitu,B,91
zara,A,65
Karim,B,
Nadia,A,88
Sabbir,B,54Schreibe ranking.py. Schreibe vor jedem Code den Plan als Kommentare an den Anfang der Datei: für jede Liste die Schlüsselspalte, die Richtung, wie Gleichstände aufgelöst werden und wohin Lücken gehören. Lass das Programm dann diese vier Bedingungen erfüllen:
- Bevor irgendetwas sortiert wird, gibt es
shape,dtypesund die Anzahl der fehlenden Noten aus. - Es gibt eine Leistungsübersicht (Merit List) aus: höchste Note zuerst, Schüler ohne Note ganz unten, ein Gleichstand bei den Noten aufgelöst nach Name in alphabetischer Reihenfolge unter Ignorieren der Groß-/Kleinschreibung, und die Zeilen neu nummeriert mit 0, 1, 2, …
- Es gibt die Top Drei mit
nlargestaus, wobei alle Personen beibehalten werden, die auf dem dritten Platz gleichauf liegen. - Es gibt die Schüler ohne Note aus, sortiert nach Name unter Ignorieren der Groß-/Kleinschreibung, damit die Lehrkraft bei ihnen nachhaken kann — und danach die ursprüngliche Tabelle, um zu beweisen, dass sie niemals verändert wurde.
Dein Programm sollte genau dies ausgeben:
(8, 3)
name str
section str
marks float64
dtype: object
Missing marks: 2
Merit list
name section marks
0 anika A 91.0
1 Mitu B 91.0
2 Nadia A 88.0
3 Rafi B 78.0
4 zara A 65.0
5 Sabbir B 54.0
6 Karim B NaN
7 Tanvir A NaN
Top three
name section marks
1 anika A 91.0
3 Mitu B 91.0
6 Nadia A 88.0
No mark yet
name section marks
5 Karim B NaN
2 Tanvir A NaN
Original, unchanged
name section marks
0 Rafi B 78.0
1 anika A 91.0
2 Tanvir A NaN
3 Mitu B 91.0
4 zara A 65.0
5 Karim B NaN
6 Nadia A 88.0
7 Sabbir B 54.0Probiere dann zwei Experimente mit der Leistungsübersicht aus:
- Entferne
key=. Welcher der beiden Schüler mit 91 Punkten kommt nun zuerst und warum? - Entferne
"name"vollständig aus den Schlüsseln und sortiere allein nachmarks. Wer kommt bei 91 zuerst — und ist dieses Ergebnis garantiert?
Lösung
Der Plan. Die Datei enthält 8 Schüler und 3 Spalten. marks weist Lücken auf, wird also als float64 eingelesen, und jede Liste, die nach Noten sortiert, muss festlegen, wohin Lücken gehören. name mischt Groß- und Kleinschreibung, sodass jeder Namensvergleich key= benötigt.
- Leistungsübersicht (Merit List) — Schlüssel
marks, dannname; Noten von hoch nach niedrig, Namen von A bis Z; ein Gleichstand bei den Noten wird über den Namen aufgelöst; Lücken am Ende (der Standard); neu nummeriert mitreset_index(drop=True). - Top Drei —
nlargest(3, "marks")mitkeep="all", damit ein geteilter dritter Platz nicht abgeschnitten wird.nlargestlässt Lücken von selbst außen vor. - Noch keine Note — filtere die Zeilen, in denen
marksfehlt, wie in den früheren Kapiteln, und sortiere dann nach Name. Erst filtern, dann sortieren. - Original — wird niemals neu zugewiesen, daher zeigt die Ausgabe von
resultsam Ende die Reihenfolge der Datei.
Ein Detail: Eine key=-Funktion wird auf jede Schlüsselspalte angewendet. Für die Leistungsübersicht gilt das auch für marks, und .str.lower() würde bei Zahlen fehlschlagen. Daher wandelt die Funktion nur Textspalten in Kleinbuchstaben um und gibt jede andere Spalte unverändert zurück.
ranking.py:
import pandas as pd
# Merit list : marks high->low, ties by name A->Z ignoring case, blanks last, renumber
# Top three : nlargest on marks, keep="all" so a shared third place is not cut
# No mark yet : filter rows with no mark, then name A->Z ignoring case
# Original : never reassigned
results = pd.read_csv("results.csv")
print(results.shape)
print(results.dtypes)
print("Missing marks:", results["marks"].isna().sum())
print()
def lower_text(col):
return col.str.lower() if col.dtype == "str" else col
merit = results.sort_values(
["marks", "name"], ascending=[False, True], key=lower_text
).reset_index(drop=True)
print("Merit list")
print(merit)
print()
print("Top three")
print(results.nlargest(3, "marks", keep="all"))
print()
print("No mark yet")
missing = results[results["marks"].isna()]
print(missing.sort_values("name", key=lower_text))
print()
print("Original, unchanged")
print(results)(8, 3)
name str
section str
marks float64
dtype: object
Missing marks: 2
Merit list
name section marks
0 anika A 91.0
1 Mitu B 91.0
2 Nadia A 88.0
3 Rafi B 78.0
4 zara A 65.0
5 Sabbir B 54.0
6 Karim B NaN
7 Tanvir A NaN
Top three
name section marks
1 anika A 91.0
3 Mitu B 91.0
6 Nadia A 88.0
No mark yet
name section marks
5 Karim B NaN
2 Tanvir A NaN
Original, unchanged
name section marks
0 Rafi B 78.0
1 anika A 91.0
2 Tanvir A NaN
3 Mitu B 91.0
4 zara A 65.0
5 Karim B NaN
6 Nadia A 88.0
7 Sabbir B 54.0Der Abgleich der Ausgabe mit dem Plan:
marksistfloat64, nichtint64, undMissing marks: 2— die Lücken wurden vor jeder Rangbildung gefunden, sodass der Leser der Leistungsübersicht weiß, dass zwei Schüler darauf fehlen und nicht etwa am Ende stehen.- Der Gleichstand bei 91 wird durch den Namen entschieden.
anikakommt vorMitu, weil der Vergleich anhand von"anika"und"mitu"durchgeführt wurde. - Die Top Drei haben hier drei Zeilen, weil der dritte Platz (88) nicht geteilt wird. Hätte Nadia ebenfalls 91 Punkte, würde
keep="all"vier Zeilen zurückgeben, anstatt eine Schülerin stillschweigend unter den Tisch fallen zu lassen. - Die Liste ohne Noten filtert zuerst und sortiert dann — dieselbe Reihenfolge „erst eingrenzen, dann Rangfolge bilden“ wie beim Muster für Top N einer Teilmenge.
- Die letzte Tabelle entspricht der Reihenfolge der Datei. Drei Listen wurden erzeugt, und
resultswurde niemals neu zugewiesen.
Die Experimente:
no_key = results.sort_values(["marks", "name"], ascending=[False, True])
marks_only = results.sort_values("marks", ascending=False)
print(no_key["name"].head(2).tolist())
print(marks_only["name"].head(2).tolist())['Mitu', 'anika']
['anika', 'Mitu']Ohne key= werden Namen Zeichen für Zeichen verglichen, und jeder Großbuchstabe kommt vor jedem Kleinbuchstaben, sodass "Mitu" vor "anika" landet — eine Reihenfolge, die darauf basiert, wie ein Name eingegeben wurde, nicht auf dem Alphabet. Allein mit marks kommt anika zufällig zuerst, weil sie weiter oben in der Datei steht. Das ist zwar dieselbe Antwort wie in der korrekten Leistungsübersicht, aber nur durch Zufall: Bei einem einzelnen Schlüssel garantiert die Standardsortierung nicht, dass gleichrangige Zeilen in der Dateireihenfolge bleiben, wie die beiden Flaschen zu 120 vorhin gezeigt haben. Eine aufgeschriebene Regel ist garantiert; ein Ergebnis, das bloß richtig aussieht, ist es nicht.
Schritt 6 von 6
Herausforderung — das Kapitel-Quiz
Zehn Fragen von leicht bis schwer. Die letzten sind absichtlich knifflig.
Melde dich an, um das Quiz zu machen