Zwei Wege, auf Daten zu zeigen: per Label und per Position
Ein DataFrame lässt sich auf zwei Arten ansprechen, und sie zu verwechseln ist der häufigste pandas-Fehler. .loc wählt per Label: Zeilenlabels aus dem Index, Spaltennamen. .iloc wählt per ganzzahliger Position, ab 0 gezählt wie bei einer Liste oder einem NumPy-Array. Beide nehmen [Zeilen, Spalten]: df.loc["AAPL", "price"] ist ein Wert, df.iloc[0, 0] der Wert der ersten Zeile und ersten Spalte. Lassen Sie den zweiten Teil weg, um ganze Zeilen zu nehmen: df.loc["AAPL"] ist die AAPL-Zeile als Series.
import pandas as pd
df = pd.DataFrame(
{"price": [184.25, 410.2, 171.0, 251.0],
"volume": [200, 50, 300, 120],
"sector": ["tech", "tech", "tech", "auto"]},
index=["AAPL", "MSFT", "GOOG", "TSLA"],
)
print(df.loc["AAPL", "price"], df.iloc[0, 0]) # 184.25 184.25 same cell, two addresses
print(df.loc["TSLA"].to_dict()) # {'price': 251.0, 'volume': 120, 'sector': 'auto'}
print(df.iloc[-1].to_dict()) # the same row: position -1 is the last
print(df.loc[["TSLA", "AAPL"], "price"]) # a list of labels picks in that order
# TSLA 251.00
# AAPL 184.25
# Name: price, dtype: float64
try:
df.loc["XXX", "price"] # a label that does not exist
except KeyError as error:
print("KeyError", error) # KeyError 'XXX'Slices: Label-Slices schließen das Ende ein
Slices verhalten sich in den beiden Systemen verschieden. Ein Positions-Slice df.iloc[1:3] folgt Pythons Regel und schließt das Ende aus: die Positionen 1 und 2. Ein Label-Slice df.loc["MSFT":"TSLA"] schließt beide Endlabels ein, da ein Label keinen natürlichen „Nachfolger“ hat. Label-Slices folgen der aktuellen Reihenfolge des Index, die nicht sortiert sein muss. Für Spalten übergeben Sie eine Liste (["price", "volume"]), um sie in der angegebenen Reihenfolge zu wählen. Vergisst man, in welchem System man ist, erhält man ohne Fehlermeldung um eins verschobene Ergebnisse.
import pandas as pd
df = pd.DataFrame(
{"price": [184.25, 410.2, 171.0, 251.0], "volume": [200, 50, 300, 120]},
index=["AAPL", "MSFT", "GOOG", "TSLA"],
)
print(df.iloc[1:3]) # positions 1 and 2: the end is excluded
# price volume
# MSFT 410.2 50
# GOOG 171.0 300
print(df.loc["MSFT":"TSLA", ["volume", "price"]]) # labels MSFT..TSLA: the end is included
# volume price
# MSFT 50 410.2
# GOOG 300 171.0
# TSLA 120 251.0
print(df.iloc[:, 0].tolist()) # the first column, by position
# [184.25, 410.2, 171.0, 251.0]Bedingungen und Zuweisung mit loc
.loc akzeptiert für die Zeilen auch eine boolesche Maske: df.loc[df["volume"] > 100, "price"] ist die Preisspalte der Zeilen, die den Test bestehen, in einem Schritt. Und .loc ist der Weg, einem gewählten Teil etwas zuzuweisen: df.loc["MSFT", "price"] = 1.0 ändert eine Zelle, df.loc[df["volume"] < 100, "volume"] = 0 alle passenden Zeilen. Vermeiden Sie verkettete Formen wie df[df["volume"] < 100]["volume"] = 0: Sie wirken auf eine temporäre Kopie. In pandas 3 ändert ein abgeleiteter Frame nie das Original; um eine Tabelle in einer Funktion zu ändern, erst df.copy(), mit .loc zuweisen und die Kopie zurückgeben.
import pandas as pd
df = pd.DataFrame(
{"price": [184.25, 410.2, 171.0, 251.0], "volume": [200, 50, 300, 120]},
index=["AAPL", "MSFT", "GOOG", "TSLA"],
)
print(df.loc[df["volume"] > 100, "price"]) # a Boolean mask for rows, a label for the column
# AAPL 184.25
# GOOG 171.00
# TSLA 251.00
# Name: price, dtype: float64
def with_price(frame, symbol, price):
out = frame.copy() # never edit the caller's table
out.loc[symbol, "price"] = price
return out
changed = with_price(df, "MSFT", 1.0)
print(changed.loc["MSFT", "price"], df.loc["MSFT", "price"]) # 1.0 410.2
fixed = df.copy()
fixed.loc[fixed["volume"] < 100, "volume"] = 0 # assign to all matching rows at once
print(fixed["volume"].tolist()) # [200, 0, 300, 120]import pandas as pd
# Integer labels are labels, not positions: a classic trap
d = pd.DataFrame({"x": [1.0, 2.0, 3.0]}, index=[10, 20, 30])
print(d.loc[20, "x"], d.iloc[0, 0]) # 2.0 1.0 label 20 is the second row
print(d.loc[10:20]["x"].tolist()) # [1.0, 2.0] labels 10 through 20, end included
print(d.iloc[0:2]["x"].tolist()) # [1.0, 2.0] positions 0 and 1, end excluded
try:
d.loc[0, "x"] # there is no label 0, even though position 0 exists
except KeyError as error:
print("KeyError", error) # KeyError 0.loc, wenn Sie die Namen kennen (ein Symbol, ein Datum, eine Spalte), und .iloc nur, wenn die Position der Punkt ist („die letzte Zeile“, „die ersten drei“). Labelbasierter Code funktioniert weiter, wenn Zeilen neu sortiert werden; positionsbasierter Code wählt stillschweigend andere Zeilen. Das bloße df[...] ist eine Abkürzung mit mehreren Bedeutungen (Spalte, Spaltenliste, Zeilenmaske), schreiben Sie in wichtigen Funktionen also ausdrücklich .loc oder .iloc. Das Lab verlangt bewusst das eine oder das andere.df.loc[zeilen_label, spalten_label]per Label;df.iloc[zeilen_pos, spalten_pos]per Position ab 0.iloc-Slices schließen das Ende aus;loc-Label-Slices ein; ein fehlendes Label löstKeyErroraus.df.loc[maske, "col"]filtert und wählt; per.locauf einer.copy()zuweisen und diese zurückgeben.
Als Nächstes: groupby und Aggregation, eine Tabelle in Gruppen teilen und jede zusammenfassen.
Lab: Was bewertet wird
- Mit
price_ofeinen Preis nach Symbol nachschlagen25 Pkt. - Mit
label_rangedie Zeilen zwischen zwei Symbolen nehmen25 Pkt. - Mit
position_rangeZeilen nach Position nehmen25 Pkt. - Mit
set_priceeinen Preis in einer Kopie korrigieren25 Pkt.