Eine Tabelle aus benannten Spalten
Ein DataFrame ist eine zweidimensionale Tabelle: eine Menge von Spalten, jede eine Series, die sich einen Index aus Zeilenlabels teilen. Er ist das Arbeitspferd der Marktdatenanalyse: eine Zeile pro Symbol oder Tag, eine Spalte pro Feld (Preis, Volumen, Rendite). Man baut ihn aus einem Dictionary von Spalten, pd.DataFrame({"price": [...], "volume": [...]}, index=symbols), oder aus einer Liste von Zeilen-Dictionaries. Jede Spalte hat ihren eigenen dtype (Preise sind float64, Volumen int64), anders als ein NumPy-Array mit einem einzigen dtype für alles.
import pandas as pd
df = pd.DataFrame(
{"price": [184.25, 410.2, 171.0], "volume": [200, 50, 300]},
index=["AAPL", "MSFT", "GOOG"],
)
print(df)
# price volume
# AAPL 184.25 200
# MSFT 410.20 50
# GOOG 171.00 300
print(df.shape, df.columns.tolist()) # (3, 2) ['price', 'volume']
print(df.dtypes.astype(str).to_dict()) # {'price': 'float64', 'volume': 'int64'}
rows = [{"symbol": "AAPL", "price": 184.25}, {"symbol": "MSFT", "price": 410.2}]
print(pd.DataFrame(rows)) # from a list of row dictionaries
# symbol price
# 0 AAPL 184.25
# 1 MSFT 410.20Spalten, neue Spalten und gefilterte Zeilen
df["price"] ist eine Spalte, eine Series; df[["price"]] mit einer Liste ist ein DataFrame mit einer Spalte. Eine neue Spalte entsteht durch Arithmetik auf Spalten: df.assign(notional=df["price"] * df["volume"]) liefert einen neuen Frame mit der zusätzlichen Spalte und lässt df unberührt (df["notional"] = ... ändert dagegen df selbst). Eine boolesche Bedingung auf einer Spalte filtert Zeilen, df[df["volume"] >= 100], und df.sort_values("volume", ascending=False) ordnet sie, wobei .head(n) die ersten n behält. All das arbeitet auf ganzen Spalten auf einmal: Laufen Sie nie mit iterrows() über Zeilen, wenn es eine Spaltenoperation gibt.
import pandas as pd
df = pd.DataFrame(
{"price": [184.25, 410.2, 171.0], "volume": [200, 50, 300]},
index=["AAPL", "MSFT", "GOOG"],
)
bigger = df.assign(notional=df["price"] * df["volume"]) # a new frame
print(bigger)
# price volume notional
# AAPL 184.25 200 36850.0
# MSFT 410.20 50 20510.0
# GOOG 171.00 300 51300.0
print(df.columns.tolist()) # ['price', 'volume'] df is unchanged
print(df[df["volume"] >= 100]) # rows that pass the test
# price volume
# AAPL 184.25 200
# GOOG 171.00 300
print(df.sort_values("volume", ascending=False).head(2)) # the two biggest volumes
# price volume
# GOOG 171.00 300
# AAPL 184.25 200Zusammenfassungen und ein Blick auf die Daten
Sehen Sie sich eine Tabelle immer an, bevor Sie ihr trauen. df.head() zeigt die ersten Zeilen, df.shape liefert (Zeilen, Spalten), df.dtypes listet den Typ jeder Spalte, df.isna().sum() zählt fehlende Werte je Spalte und df.describe() fasst die numerischen Spalten zusammen (Anzahl, Mittelwert, Standardabweichung, Minimum, Quartile, Maximum). Spaltenmethoden wie df.mean() liefern einen Wert pro Spalte; df.sum(axis=1) einen pro Zeile. Ein dtype object oder str, wo Zahlen erwartet wurden, bedeutet meist, dass Text in die Spalte geraten ist.
import pandas as pd
df = pd.DataFrame(
{"price": [184.25, 410.2, 171.0], "volume": [200, 50, 300]},
index=["AAPL", "MSFT", "GOOG"],
)
print(df.describe().loc[["count", "mean", "max"]])
# price volume
# count 3.00 3.000000
# mean 255.15 183.333333
# max 410.20 300.000000
print(df.mean().to_dict()) # {'price': 255.15, 'volume': 183.33333333333334}
print(df.sum(axis=1).tolist()) # [384.25, 460.2, 471.0] one value per row
print(df.isna().sum().to_dict()) # {'price': 0, 'volume': 0}
# Changing a copy never changes the original (pandas 3 copies on write)
cheap = df[df["price"] < 200].copy()
cheap.loc["AAPL", "price"] = 0.0
print(df.loc["AAPL", "price"]) # 184.25import pandas as pd
rows = [
{"symbol": "AAPL", "price": 184.25, "volume": 200},
{"symbol": "MSFT", "price": 410.2, "volume": 50},
]
df = pd.DataFrame(rows).set_index("symbol") # make a column the row labels
print(df)
# price volume
# symbol
# AAPL 184.25 200
# MSFT 410.20 50
print(df.rename(columns={"price": "px"}).columns.tolist()) # ['px', 'volume']
print(df.drop(columns="volume").columns.tolist()) # ['price']
print(df.reset_index().columns.tolist()) # ['symbol', 'price', 'volume']assign, boolesches Filtern und sort_values, die alle neue Frames liefern. Der klassische Fehler ist, eine neue Spalte ins Argument zu schreiben, wodurch sie stillschweigend in der Tabelle des Aufrufers landet. Die Lab-Tests vergleichen das Argument davor und danach genau deshalb.pd.DataFrame({spalte: werte}, index=labels);df["c"]ist eine Series,df[["c"]]ein DataFrame; jede Spalte hat ihren dtype.assignfügt einem neuen Frame eine Spalte hinzu;df[maske]filtert Zeilen;sort_values(...).head(n)nimmt die besten n.- Erst ansehen:
shape,dtypes,head(),describe(),isna().sum(); ändern Sie nie den Frame des Aufrufers.
Als Nächstes: Daten mit loc und iloc auswählen, die zwei präzisen Wege, Zeilen und Spalten nach Label oder Position zu wählen.
Lab: Was bewertet wird
- Mit
make_frameeine Tabelle aus Preisen und Volumen bauen25 Pkt. - Mit
add_notionaleine Spalte mit dem Handelswert ergänzen25 Pkt. - Mit
filter_liquidnur die liquiden Zeilen behalten25 Pkt. - Mit
top_bydie Zeilen nach einer beliebigen Spalte ordnen25 Pkt.