Python für Data Science: NumPy, Pandas und Scikit-Learn im Jahr 2026
Ein umfassender Leitfaden zu Python Data Science mit NumPy, Pandas 2.2 und Scikit-Learn 1.6. Von Array-Operationen über DataFrame-Manipulation bis zur vollständigen ML-Pipeline — mit praxisnahen Codebeispielen für den Einstieg und fortgeschrittene Anwendungen.

Python hat sich als die dominierende Programmiersprache im Bereich Data Science etabliert — und das nicht ohne Grund. Das Zusammenspiel von NumPy für numerische Berechnungen, Pandas für Datenmanipulation und Scikit-Learn für maschinelles Lernen bildet ein Ökosystem, das sowohl Einsteigern als auch erfahrenen Data Scientists eine durchgängige Werkzeugkette bietet. Im Jahr 2026 sind diese drei Bibliotheken ausgereifter denn je: NumPy 2.1 bringt verbesserte Typsicherheit, Pandas 2.2 setzt auf Copy-on-Write als Standard, und Scikit-Learn 1.6 erweitert die Pipeline-Funktionalität erheblich. Dieser Artikel führt Schritt für Schritt durch den gesamten Workflow — von rohen Daten bis zum produktionsfertigen Modell.
Alle Codebeispiele verwenden Python 3.12, NumPy 2.1, Pandas 2.2 und Scikit-Learn 1.6. Die Installation erfolgt über pip install numpy pandas scikit-learn — für reproduzierbare Umgebungen empfiehlt sich uv oder pip-tools mit einer festgelegten requirements.txt.
NumPy Array-Operationen für effiziente Berechnungen
NumPy bildet das Fundament des gesamten Python-Data-Science-Stacks. Während Python-Listen flexibel, aber langsam sind, arbeiten NumPy-Arrays mit homogenen Datentypen und fester Größe — was vektorisierte Operationen ermöglicht, die um Größenordnungen schneller als herkömmliche Schleifen laufen. Der Schlüssel liegt darin, Berechnungen möglichst als Array-Operationen statt als elementweise Schleifen zu formulieren.
# numpy_basics.py
import numpy as np
# Create arrays from different sources
prices = np.array([29.99, 49.99, 19.99, 99.99, 39.99])
quantities = np.arange(1, 6) # [1, 2, 3, 4, 5]
# Vectorized arithmetic — no loops needed
revenue = prices * quantities
print(revenue) # [29.99, 99.98, 59.97, 399.96, 199.95]
# Statistical aggregations
print(f"Total revenue: ${revenue.sum():.2f}") # $789.85
print(f"Mean price: ${prices.mean():.2f}") # $47.99
print(f"Std deviation: ${prices.std():.2f}") # $27.64
# Boolean indexing — filter without loops
premium_mask = prices > 40
premium_items = prices[premium_mask] # [49.99, 99.99]Boolean Indexing verdient besondere Beachtung, da es eines der mächtigsten Konzepte in NumPy darstellt. Anstatt eine Schleife zu schreiben, die jedes Element prüft und in eine neue Liste kopiert, erzeugt der Vergleich prices > 40 ein Boolean-Array gleicher Länge. Dieses Array dient dann als Maske: Nur die Positionen mit True werden aus dem ursprünglichen Array extrahiert. Das Resultat ist nicht nur kompakterer Code, sondern auch deutlich bessere Performance — bei großen Datensätzen kann der Unterschied zwischen Sekunden und Millisekunden liegen.
Umformen und Broadcasting in NumPy
Sobald Daten mehrdimensional werden — etwa Verkaufszahlen über mehrere Produkte und Monate hinweg — wird das Verständnis von Achsen und Formen unverzichtbar. NumPy operiert standardmäßig über alle Elemente eines Arrays, lässt sich aber mit dem axis-Parameter gezielt auf Zeilen oder Spalten einschränken. Broadcasting erlaubt zudem Operationen zwischen Arrays unterschiedlicher Form, solange bestimmte Kompatibilitätsregeln erfüllt sind.
# numpy_reshape.py
import numpy as np
# Monthly sales data: 4 products x 3 months
sales = np.array([
[120, 150, 130], # Product A
[200, 180, 220], # Product B
[90, 110, 95], # Product C
[300, 280, 310], # Product D
])
# Column-wise mean (average per month)
monthly_avg = sales.mean(axis=0) # [177.5, 180.0, 188.75]
# Row-wise sum (total per product)
product_totals = sales.sum(axis=1) # [400, 600, 295, 890]
# Normalize each product relative to its own max
normalized = sales / sales.max(axis=1, keepdims=True)
# keepdims=True preserves the shape for broadcasting
print(normalized[0]) # [0.8, 1.0, 0.867] — Product A relative to its peak
# Reshape for Scikit-Learn (requires 2D input)
flat_sales = sales.flatten() # 1D array of 12 values
reshaped = flat_sales.reshape(-1, 1) # 12x1 column vectorDer axis-Parameter folgt einer einfachen Logik: axis=0 operiert entlang der Zeilen (also spaltenweise zusammenfassend), während axis=1 entlang der Spalten arbeitet (zeilenweise zusammenfassend). Das Argument keepdims=True spielt beim Broadcasting eine entscheidende Rolle. Ohne dieses Argument hätte sales.max(axis=1) die Form (4,) — ein eindimensionaler Vektor. Mit keepdims=True bleibt die Form bei (4, 1), was NumPy erlaubt, die Division elementweise auf jede Spalte anzuwenden. Dieses Zusammenspiel von Achsen und Formen zu beherrschen ist essentiell, bevor Daten an Scikit-Learn übergeben werden, das grundsätzlich zweidimensionale Eingaben erwartet.
Pandas DataFrame-Manipulation und Datenbereinigung
Nach den numerischen Grundlagen mit NumPy folgt der nächste Schritt im Data-Science-Workflow: das Laden, Inspizieren und Bereinigen realer Daten. Pandas stellt dafür den DataFrame bereit — eine tabellarische Datenstruktur mit benannten Spalten und einem Index. In der Praxis verbringen Data Scientists den Großteil ihrer Zeit mit der Datenbereinigung, weshalb ein systematischer Ansatz unverzichtbar ist. Die Methode des Chainings erlaubt es, alle Bereinigungsschritte in einer einzigen, nachvollziehbaren Sequenz zu formulieren.
# pandas_cleaning.py
import pandas as pd
import numpy as np
# Load and inspect raw data
df = pd.read_csv("candidates.csv")
print(df.shape) # (1500, 8)
print(df.dtypes) # Check column types
print(df.isna().sum()) # Count missing values per column
# Clean in a reproducible chain
df_clean = (
df
.dropna(subset=["salary", "experience_years"]) # Drop rows missing critical fields
.assign(
salary=lambda x: x["salary"].clip(lower=20000, upper=500000), # Cap outliers
experience_years=lambda x: x["experience_years"].astype(int),
hired_date=lambda x: pd.to_datetime(x["hired_date"], errors="coerce"),
)
.drop_duplicates(subset=["email"]) # Remove duplicate candidates
.query("experience_years >= 0") # Filter invalid entries
.reset_index(drop=True)
)
print(f"Cleaned: {len(df)} -> {len(df_clean)} rows")Method Chaining — also das Aneinanderreihen von DataFrame-Methoden mit dem Punkt-Operator — hat sich als Best Practice in der Pandas-Welt durchgesetzt. Der entscheidende Vorteil: Jeder Schritt ist deklarativ und in sich abgeschlossen. Die .assign()-Methode mit Lambda-Funktionen ermöglicht es, neue Spalten zu erstellen oder bestehende zu überschreiben, ohne den Zwischenzustand in separaten Variablen speichern zu müssen. Das x in den Lambda-Ausdrücken bezieht sich dabei immer auf den DataFrame im aktuellen Zustand der Kette — also bereits nach dem .dropna() im obigen Beispiel. Wer diesen Stil konsequent anwendet, erhält reproduzierbare Transformationen, die sich leicht testen und debuggen lassen.
Seit Pandas 2.2 ist Copy-on-Write (CoW) das Standardverhalten. Das bedeutet: Wenn ein DataFrame einer neuen Variable zugewiesen wird, teilen sich beide zunächst denselben Speicher. Erst bei einer Modifikation wird tatsächlich eine Kopie erstellt. Dadurch entfallen die berüchtigten SettingWithCopyWarning-Meldungen, und der Code wird sowohl sicherer als auch speichereffizienter. Wer von älteren Pandas-Versionen migriert, sollte beachten, dass In-Place-Modifikationen über verkettete Indizierung (df["col"][0] = x) nicht mehr funktionieren — stattdessen ist .loc[] oder .assign() zu verwenden.
GroupBy-Aggregationen und Feature Engineering mit Pandas
Nach der Bereinigung folgt die Aggregation und das Feature Engineering — zwei Schritte, die direkt in die Modellierung einfließen. Mit .groupby() lassen sich Daten nach Kategorien zusammenfassen und statistische Kennzahlen berechnen. Darüber hinaus können aus bestehenden Spalten neue Features abgeleitet werden, die einem Machine-Learning-Modell zusätzliche Signale liefern. Die Kombination aus GroupBy-Aggregationen und .transform() ermöglicht es, gruppierte Berechnungen direkt auf die ursprüngliche DataFrame-Struktur zurückzuführen.
# pandas_groupby.py
import pandas as pd
# Aggregate candidate stats by department
dept_stats = (
df_clean
.groupby("department")
.agg(
avg_salary=("salary", "mean"),
median_experience=("experience_years", "median"),
headcount=("email", "count"),
max_salary=("salary", "max"),
)
.sort_values("avg_salary", ascending=False)
)
print(dept_stats.head())
# Create features for ML: encode categorical + add aggregated stats
df_features = (
df_clean
.assign(
# Ratio of individual salary to department average
salary_ratio=lambda x: x["salary"] / x.groupby("department")["salary"].transform("mean"),
# Time since hire in days
tenure_days=lambda x: (pd.Timestamp.now() - x["hired_date"]).dt.days,
# Binary encoding
is_senior=lambda x: (x["experience_years"] >= 5).astype(int),
)
)Die Methode .transform() unterscheidet sich grundlegend von .agg(): Während .agg() die Daten auf eine Zeile pro Gruppe reduziert, gibt .transform() ein Ergebnis in der gleichen Länge wie der ursprüngliche DataFrame zurück. Im obigen Beispiel berechnet .transform("mean") den Durchschnittslohn pro Abteilung und weist diesen Wert jeder einzelnen Zeile der jeweiligen Abteilung zu. Dadurch kann das Verhältnis des individuellen Gehalts zum Abteilungsdurchschnitt direkt als neues Feature berechnet werden — ein klassisches Beispiel für Feature Engineering, das einem Modell den relativen Kontext eines Datenpunkts vermittelt, statt nur den absoluten Wert.
Bereit für deine Data Science & ML-Interviews?
Übe mit unseren interaktiven Simulatoren, Flashcards und technischen Tests.
Eine Scikit-Learn Pipeline von Grund auf erstellen
Mit bereinigten Daten und vorbereiteten Features kann nun das eigentliche Modell gebaut werden. Scikit-Learn verfolgt dabei einen Pipeline-Ansatz: Vorverarbeitung und Modelltraining werden in einer einzigen Kette zusammengefasst, was Fehler bei der Transformation neuer Daten verhindert und den Code erheblich vereinfacht. Der ColumnTransformer ermöglicht es, unterschiedliche Vorverarbeitungsschritte auf numerische und kategorische Spalten gleichzeitig anzuwenden.
# sklearn_pipeline.py
from sklearn.model_selection import train_test_split
from sklearn.pipeline import Pipeline
from sklearn.compose import ColumnTransformer
from sklearn.preprocessing import StandardScaler, OneHotEncoder
from sklearn.ensemble import GradientBoostingClassifier
from sklearn.metrics import classification_report
import pandas as pd
# Define column groups
numeric_features = ["salary", "experience_years", "salary_ratio", "tenure_days"]
categorical_features = ["department", "role_level"]
target = "promoted"
# Split before any preprocessing
X = df_features[numeric_features + categorical_features]
y = df_features[target]
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.2, random_state=42, stratify=y
)
# Build the preprocessing + model pipeline
preprocessor = ColumnTransformer(
transformers=[
("num", StandardScaler(), numeric_features), # Scale numeric columns
("cat", OneHotEncoder(handle_unknown="ignore"), categorical_features), # Encode categories
]
)
pipeline = Pipeline([
("preprocessor", preprocessor),
("classifier", GradientBoostingClassifier(
n_estimators=200,
learning_rate=0.1,
max_depth=4,
random_state=42,
)),
])
# Train and evaluate
pipeline.fit(X_train, y_train)
y_pred = pipeline.predict(X_test)
print(classification_report(y_test, y_pred))Der ColumnTransformer löst eines der häufigsten Probleme in ML-Projekten: Numerische und kategorische Daten erfordern völlig unterschiedliche Vorverarbeitungen. Numerische Spalten werden hier mit StandardScaler auf Mittelwert 0 und Standardabweichung 1 normalisiert, während kategorische Spalten mittels OneHotEncoder in binäre Vektoren umgewandelt werden. Das Argument handle_unknown="ignore" stellt sicher, dass das Modell bei Vorhersagen auf unbekannte Kategorien nicht abstürzt, sondern diese als Nullvektor kodiert. Der entscheidende Vorteil der Pipeline gegenüber einzelnen Transformationsschritten: Der train_test_split findet vor jeglicher Vorverarbeitung statt, wodurch Information Leakage vom Test- in den Trainingsdatensatz ausgeschlossen wird.
Kreuzvalidierung und Hyperparameter-Tuning
Ein einzelner Train-Test-Split liefert nur eine Punktschätzung der Modellleistung. Kreuzvalidierung teilt die Trainingsdaten mehrfach in unterschiedliche Folds auf und liefert so ein robusteres Bild. In Kombination mit GridSearchCV lässt sich gleichzeitig der optimale Satz an Hyperparametern finden — und das vollautomatisch über die gesamte Pipeline hinweg, einschließlich der Vorverarbeitungsschritte.
# sklearn_tuning.py
from sklearn.model_selection import cross_val_score, GridSearchCV
import numpy as np
# 5-fold cross-validation on the full pipeline
scores = cross_val_score(pipeline, X_train, y_train, cv=5, scoring="f1")
print(f"F1 scores: {scores}")
print(f"Mean F1: {scores.mean():.3f} (+/- {scores.std() * 2:.3f})")
# Grid search over hyperparameters
param_grid = {
"classifier__n_estimators": [100, 200, 300],
"classifier__max_depth": [3, 4, 5],
"classifier__learning_rate": [0.05, 0.1, 0.2],
}
grid_search = GridSearchCV(
pipeline,
param_grid,
cv=5,
scoring="f1",
n_jobs=-1, # Use all CPU cores
verbose=1,
)
grid_search.fit(X_train, y_train)
print(f"Best params: {grid_search.best_params_}")
print(f"Best F1: {grid_search.best_score_:.3f}")
# Evaluate the best model on held-out test set
best_model = grid_search.best_estimator_
print(classification_report(y_test, best_model.predict(X_test)))Die Doppel-Unterstrich-Syntax (classifier__n_estimators) ist ein zentrales Konzept in Scikit-Learn-Pipelines. Sie adressiert den Parameter n_estimators des Pipeline-Schritts mit dem Namen classifier. Dadurch können Hyperparameter jeder Stufe der Pipeline — auch des Preprocessors — im Grid Search durchsucht werden. Beispielsweise ließe sich mit preprocessor__num__with_mean steuern, ob der StandardScaler den Mittelwert abzieht. Der Parameter n_jobs=-1 nutzt alle verfügbaren CPU-Kerne parallel, was bei 27 Parameterkombinationen (3 x 3 x 3) mit jeweils 5 Folds insgesamt 135 Modelltrainings bedeutet — eine Aufgabe, die von Parallelisierung erheblich profitiert.
Ein häufiger Fehler bei der Modellentwicklung ist Data Leakage: Wenn Informationen aus dem Testdatensatz in den Trainingsprozess einfließen, erscheinen die Metriken künstlich gut — das Modell versagt dann in der Praxis. Die häufigsten Ursachen sind: (1) Feature-Skalierung oder Encoding vor dem Train-Test-Split, (2) Features, die zum Zeitpunkt der Vorhersage nicht verfügbar wären, und (3) Duplikate zwischen Train und Test. Die Pipeline-Architektur von Scikit-Learn schützt automatisch vor Punkt (1), da der Scaler nur auf Trainingsdaten gefittet wird. Für die Punkte (2) und (3) ist jedoch manuelle Sorgfalt erforderlich.
Modelle speichern und laden für den Produktiveinsatz
Nachdem das beste Modell identifiziert und evaluiert wurde, muss es für den produktiven Einsatz serialisiert werden. Die Bibliothek joblib ist die empfohlene Methode für Scikit-Learn-Modelle, da sie NumPy-Arrays effizienter als Pythons pickle speichert. Der entscheidende Punkt: Es wird nicht nur der Klassifikator gespeichert, sondern die gesamte Pipeline einschließlich aller Vorverarbeitungsschritte. Damit ist sichergestellt, dass neue Daten bei der Vorhersage identisch transformiert werden wie die Trainingsdaten.
# sklearn_export.py
import joblib
from pathlib import Path
# Save the complete pipeline (preprocessor + model)
model_dir = Path("models")
model_dir.mkdir(exist_ok=True)
joblib.dump(best_model, model_dir / "promotion_model_v1.joblib")
# Load and predict in a different process
loaded_model = joblib.load(model_dir / "promotion_model_v1.joblib")
new_data = pd.DataFrame({
"salary": [75000],
"experience_years": [4],
"salary_ratio": [1.05],
"tenure_days": [730],
"department": ["Engineering"],
"role_level": ["Mid"],
})
prediction = loaded_model.predict(new_data)
probability = loaded_model.predict_proba(new_data)[:, 1]
print(f"Promoted: {bool(prediction[0])}, Confidence: {probability[0]:.2%}")Das Speichern der gesamten Pipeline statt nur des Modells ist ein häufig unterschätzter Aspekt. Wenn der StandardScaler separat gespeichert und geladen werden müsste, steigt das Risiko von Inkonsistenzen bei der Transformation neuer Daten erheblich. Mit joblib.dump() wird die komplette Kette — ColumnTransformer, Scaler, OneHotEncoder und GradientBoostingClassifier — in einer einzigen Datei persistiert. Bei der Vorhersage genügt dann ein .predict()-Aufruf auf dem geladenen Objekt, und die gesamte Vorverarbeitung läuft automatisch ab. Für Produktivsysteme empfiehlt sich zusätzlich eine Versionierung der Modelldateien sowie das Speichern der Scikit-Learn-Version in den Metadaten, um Kompatibilitätsprobleme bei Updates zu vermeiden.
Fazit
Der Python-Data-Science-Stack aus NumPy, Pandas und Scikit-Learn bietet im Jahr 2026 ein ausgereiftes und kohärentes Werkzeugset für den gesamten ML-Workflow. Die wichtigsten Erkenntnisse aus diesem Tutorial:
- NumPy bildet das Fundament: Vektorisierte Operationen, Boolean Indexing und ein sicheres Verständnis von Achsen und Formen sind die Grundlage für effiziente Datenverarbeitung.
- Pandas 2.2 mit Copy-on-Write macht die Datenbereinigung sicherer und speichereffizienter. Method Chaining und
.transform()ermöglichen reproduzierbare, gut lesbare Transformationspipelines. - Scikit-Learn Pipelines fassen Vorverarbeitung und Modelltraining in einer Einheit zusammen und schützen so vor Data Leakage. Der
ColumnTransformerlöst das Problem unterschiedlicher Datentypen elegant. - Kreuzvalidierung und Grid Search liefern robuste Leistungsschätzungen und automatisieren die Hyperparameter-Optimierung über die gesamte Pipeline.
- Modellserialisierung mit
joblibsichert die komplette Pipeline für den Produktiveinsatz — nicht nur den Klassifikator.
Wer diese Grundlagen beherrscht, hat das Rüstzeug, um reale Data-Science-Projekte strukturiert und professionell anzugehen — von der ersten Datenexploration bis zum deploybaren Modell.
Fang an zu üben!
Teste dein Wissen mit unseren Interview-Simulatoren und technischen Tests.
Tags
Teilen
Verwandte Artikel

Machine-Learning-Algorithmen erklärt: Der vollständige Leitfaden für technische Interviews
Ein umfassender Leitfaden zu den wichtigsten Machine-Learning-Algorithmen für technische Vorstellungsgespräche 2026 – von linearen Modellen über Ensemble-Methoden bis hin zu unüberwachtem Lernen mit Python und scikit-learn.

Top 25 Data-Science-Interviewfragen 2026 – Mit Lösungen und Code
Die 25 wichtigsten Data-Science-Interviewfragen für 2026, mit vollständigen Antworten, Python-Code und praktischen Beispielen für Statistics, ML, SQL und System Design.