SemaTrain Logo Ein Fachportal von SemaTrain

Datenanalyse mit Pandas (Python)

Sie arbeiten mit DataFrames: Daten laden, bereinigen, filtern, aggregieren und visualisieren – praxisnah mit SemaTrain-Beispieldaten (Kurs, Ort, Format, Dauer, Preis).

Hinweis: Werte/Dateien sind Beispieldaten (didaktisch, nicht verbindlich).

Python Schulung – Kursbezug

Dieses Kapitel ist Teil des Lernpfads zur Python Schulung. Termine & Buchung laufen über SemaTrain.de.

Ziel: Sie können Kurs-/Teilnehmerdaten in Pandas laden, prüfen, aggregieren und als kompakte Auswertung ausgeben (Beispieldaten).

Merksatz: Pandas ist „Excel für Code“ – wichtig ist nicht jedes Feature, sondern ein sicherer Workflow: laden → prüfen → bereinigen → auswerten.

Worum geht’s?

Lehr-/Lernziele

Nach diesem Kapitel können Sie …

Wie Sie die Ziele erreichen: Wir nutzen einen SemaTrain-Use-Case (Kursangebote, Orte, Formate – Beispielwerte). Das Quiz prüft LZ1–LZ4. Im Mini-Projekt bauen Sie eine Auswertung „Umsatz (Beispiel) nach Standort/Format“.

Setup (kurz)

Typisch im Notebook oder im venv. (Die Befehle sind Beispiele.)

Import: pandas + numpy (Optional: matplotlib) (Python)
# Installation (Beispiel):
# pip install pandas numpy matplotlib

import pandas as pd
import numpy as np

DataFrame: Erstellen & Prüfen

Wir starten mit Beispieldaten: Kurs, Standort, Format, Dauer, Preis.

DataFrame erstellen + prüfen (LZ1) (Python)
import pandas as pd

daten = [
    {"kurs": "Python Schulung", "standort": "Hamburg", "format": "Praesenz", "dauer_tage": 3, "preis_euro": 1490.00},
    {"kurs": "Python Schulung", "standort": "Berlin",  "format": "Online",   "dauer_tage": 3, "preis_euro": 1390.00},
    {"kurs": "Python Schulung", "standort": "Muenchen","format": "Praesenz", "dauer_tage": 4, "preis_euro": 1890.00},
    {"kurs": "Python Schulung", "standort": "Koeln",   "format": "Online",   "dauer_tage": 2, "preis_euro":  990.00},
]

df = pd.DataFrame(daten)

print(df.head())
print(df.info())
print(df.describe(numeric_only=True))

Bereinigung: Missing Values & neue Spalten

Fehlende Werte sind normal. Wichtig: bewusst entscheiden, ob Sie löschen oder ersetzen.

Missing Values + neue Spalten (LZ2) (Python)
import pandas as pd
import numpy as np

daten = [
    {"kurs": "Python Schulung", "standort": "Hamburg", "format": "Praesenz", "dauer_tage": 3, "preis_euro": 1490.00},
    {"kurs": "Python Schulung", "standort": "Berlin",  "format": "Online",   "dauer_tage": 3, "preis_euro": None},  # fehlt
    {"kurs": "Python Schulung", "standort": "Koeln",   "format": "Online",   "dauer_tage": 2, "preis_euro":  990.00},
]

df = pd.DataFrame(daten)

# 1) Missing Values prüfen
print(df.isna().sum())

# 2) Beispiel: fehlenden Preis mit Median ersetzen (Beispielregel)
median_preis = df["preis_euro"].median(skipna=True)
df["preis_euro"] = df["preis_euro"].fillna(median_preis)

# 3) Neue Spalte: Tagespreis
df["tagespreis_euro"] = df["preis_euro"] / df["dauer_tage"]

# 4) Typen (optional): dauer_tage als int
df["dauer_tage"] = df["dauer_tage"].astype(int)

print(df)

Auswertung: Filtern, GroupBy, Pivot

Filtern & Sortieren

Filtern + Sortieren (LZ3) (Python)
import pandas as pd

df = pd.DataFrame([
    {"standort":"Hamburg","format":"Praesenz","dauer_tage":3,"preis_euro":1490.00},
    {"standort":"Berlin","format":"Online","dauer_tage":3,"preis_euro":1390.00},
    {"standort":"Muenchen","format":"Praesenz","dauer_tage":4,"preis_euro":1890.00},
    {"standort":"Koeln","format":"Online","dauer_tage":2,"preis_euro": 990.00},
])

# Alle Praesenz-Kurse, nach Preis absteigend
praesenz = df[df["format"] == "Praesenz"].sort_values("preis_euro", ascending=False)
print(praesenz)

groupby: Kennzahlen pro Gruppe

groupby + agg (LZ3) (Python)
import pandas as pd

df = pd.DataFrame([
    {"standort":"Hamburg","format":"Praesenz","teilnehmer":12,"preis_euro":1490.00},
    {"standort":"Hamburg","format":"Praesenz","teilnehmer": 9,"preis_euro":1490.00},
    {"standort":"Berlin","format":"Online","teilnehmer":15,"preis_euro":1390.00},
    {"standort":"Berlin","format":"Online","teilnehmer":11,"preis_euro":1390.00},
])

# Beispiel: Umsatz (nicht verbindlich) = teilnehmer * preis
df["umsatz_beispiel"] = df["teilnehmer"] * df["preis_euro"]

auswertung = (
    df.groupby(["standort","format"])
      .agg(anzahl_termine=("teilnehmer","size"),
           teilnehmer_summe=("teilnehmer","sum"),
           umsatz_beispiel=("umsatz_beispiel","sum"))
      .reset_index()
      .sort_values("umsatz_beispiel", ascending=False)
)

print(auswertung)
Pivot-Tabelle (kompakt)
Pivot-Tabelle (LZ3) (Python)
import pandas as pd

df = pd.DataFrame([
    {"standort":"Hamburg","format":"Praesenz","umsatz_beispiel":30000},
    {"standort":"Hamburg","format":"Online","umsatz_beispiel":18000},
    {"standort":"Berlin","format":"Online","umsatz_beispiel":26000},
])

pivot = pd.pivot_table(
    df,
    index="standort",
    columns="format",
    values="umsatz_beispiel",
    aggfunc="sum",
    fill_value=0
)

print(pivot)

Daten kombinieren: merge (Join)

Typisch: Fakten-Tabelle (Termine) + Lookup-Tabelle (Standortregion, Ansprechpartner, etc.).

merge: Termine + Standortinfo (LZ4) (Python)
import pandas as pd

termine = pd.DataFrame([
    {"standort":"Hamburg","format":"Praesenz","teilnehmer":12},
    {"standort":"Berlin","format":"Online","teilnehmer":15},
])

standorte = pd.DataFrame([
    {"standort":"Hamburg","region":"Nord"},
    {"standort":"Berlin","region":"Ost"},
    {"standort":"Muenchen","region":"Sued"},
])

df = termine.merge(standorte, on="standort", how="left")
print(df)

Optional: schneller Plot

Für schnelle Checks reicht oft pandas.DataFrame.plot. (Im Notebook ideal.)

Bar-Plot (optional, LZ4) (Python)
import pandas as pd
import matplotlib.pyplot as plt

auswertung = pd.DataFrame([
    {"standort":"Hamburg","umsatz_beispiel":48000},
    {"standort":"Berlin","umsatz_beispiel":52000},
    {"standort":"Muenchen","umsatz_beispiel":61000},
])

ax = auswertung.set_index("standort")["umsatz_beispiel"].plot(kind="bar", title="Umsatz (Beispiel) je Standort")
ax.set_ylabel("EUR")
plt.tight_layout()
plt.show()

Praxisaufgabe (Mini)

Sie bauen eine kleine Auswertung aus „Terminen“ (Beispieldaten) und geben eine Ranking-Tabelle aus.

Beitrag zu den Lehr-/Lernzielen: LZ1 (prüfen), LZ2 (bereinigen), LZ3 (groupby), LZ4 (merge/pivot optional).

  1. (LZ1) Erstellen Sie einen DataFrame termine mit Spalten: standort, format, teilnehmer, preis_euro (Beispielwerte).
  2. (LZ2) Fügen Sie absichtlich einen fehlenden Preis (None) ein und ersetzen Sie ihn (z.B. mit Median).
  3. (LZ3) Berechnen Sie umsatz_beispiel = teilnehmer * preis_euro und aggregieren Sie nach standort.
  4. (LZ3) Sortieren Sie die Standorte nach Umsatz absteigend und geben Sie Top 3 aus.
  5. (Bonus, LZ4) Mergen Sie eine Standort-Tabelle (Region) dazu.
Lösungsvorschlag anzeigen
Lösung: Ranking je Standort (Beispieldaten) (Python)
import pandas as pd

termine = pd.DataFrame([
    {"standort":"Hamburg","format":"Praesenz","teilnehmer":12,"preis_euro":1490.00},
    {"standort":"Hamburg","format":"Praesenz","teilnehmer": 9,"preis_euro":1490.00},
    {"standort":"Berlin","format":"Online","teilnehmer":15,"preis_euro":1390.00},
    {"standort":"Berlin","format":"Online","teilnehmer":11,"preis_euro":None},      # fehlt
    {"standort":"Muenchen","format":"Praesenz","teilnehmer":10,"preis_euro":1890.00},
])

# LZ1: prüfen
print(termine.head())
print(termine.isna().sum())

# LZ2: missing price füllen (Beispiel)
median_preis = termine["preis_euro"].median(skipna=True)
termine["preis_euro"] = termine["preis_euro"].fillna(median_preis)

# LZ3: Umsatz (Beispiel) berechnen + Aggregation
termine["umsatz_beispiel"] = termine["teilnehmer"] * termine["preis_euro"]

ranking = (
    termine.groupby("standort")
           .agg(teilnehmer_summe=("teilnehmer","sum"),
                umsatz_beispiel=("umsatz_beispiel","sum"))
           .reset_index()
           .sort_values("umsatz_beispiel", ascending=False)
)

print("Ranking (Top 3):")
print(ranking.head(3))

# Bonus LZ4: merge Region
standorte = pd.DataFrame([
    {"standort":"Hamburg","region":"Nord"},
    {"standort":"Berlin","region":"Ost"},
    {"standort":"Muenchen","region":"Sued"},
])

ranking_mit_region = ranking.merge(standorte, on="standort", how="left")
print(ranking_mit_region)

Kurz-Takeaways

Quiz: Datenanalyse mit Pandas (SemaTrain-Beispieldaten)

1. (LZ1) Womit prüfen Sie schnell, welche Spalten/Typen ein DataFrame hat?

2. (LZ2) Wie ersetzen Sie fehlende Werte in einer Spalte am häufigsten?

3. (LZ3) Wozu dient groupby() typischerweise?

4. (LZ4) Wofür ist merge() gedacht?

Praxisaufgabe

Mini-Projekt: Standort-Report (Ranking + Pivot + Merge)

Sie erstellen einen kompakten Report aus Termindaten (Beispieldaten): Umsatz (Beispiel) nach Standort/Format, inklusive Bereinigung, Ranking, Pivot und optional Plot.

Beitrag zu den Lehr-/Lernzielen:
LZ1 (DF prüfen), LZ2 (Missing/Typen/Spalten), LZ3 (groupby/pivot), LZ4 (merge + optional Visualisierung).

Aufgabe

Lösung anzeigen
Lösung: Standort-Report (Pandas-Workflow, Beispiellogik) (Python)
import pandas as pd

# ===== 1) Beispieldaten (LZ1) =====
termine = pd.DataFrame([
    {"kurs":"Python Schulung","standort":"Hamburg","format":"Praesenz","dauer_tage":3,"teilnehmer":12,"preis_euro":1490.00},
    {"kurs":"Python Schulung","standort":"Hamburg","format":"Online","dauer_tage":3,"teilnehmer":14,"preis_euro":1290.00},
    {"kurs":"Python Schulung","standort":"Berlin","format":"Online","dauer_tage":3,"teilnehmer":15,"preis_euro":1390.00},
    {"kurs":"Python Schulung","standort":"Berlin","format":"Online","dauer_tage":3,"teilnehmer":11,"preis_euro":None},     # fehlt
    {"kurs":"Python Schulung","standort":"Muenchen","format":"Praesenz","dauer_tage":4,"teilnehmer":10,"preis_euro":1890.00},
    {"kurs":"Python Schulung","standort":"Muenchen","format":"Praesenz","dauer_tage":4,"teilnehmer": 8,"preis_euro":1890.00},
    {"kurs":"Python Schulung","standort":"Koeln","format":"Online","dauer_tage":2,"teilnehmer": 9,"preis_euro": 990.00},
    {"kurs":"Python Schulung","standort":"Koeln","format":"Online","dauer_tage":2,"teilnehmer":13,"preis_euro":1090.00},
])

# ===== 2) Prüfen (LZ1) =====
print("HEAD:")
print(termine.head())
print("\nINFO:")
print(termine.info())
print("\nDESCRIBE:")
print(termine.describe(numeric_only=True))
print("\nMISSING:")
print(termine.isna().sum())

# ===== 3) Bereinigen + neue Spalten (LZ2) =====
termine["dauer_tage"] = termine["dauer_tage"].astype(int)
termine["teilnehmer"] = termine["teilnehmer"].astype(int)

median_preis = termine["preis_euro"].median(skipna=True)
termine["preis_euro"] = termine["preis_euro"].fillna(median_preis)

termine["umsatz_beispiel"] = termine["teilnehmer"] * termine["preis_euro"]
termine["tagespreis_euro"] = termine["preis_euro"] / termine["dauer_tage"]

# ===== 4) Ranking (LZ3) =====
ranking = (
    termine.groupby("standort")
           .agg(termine_anzahl=("kurs","size"),
                teilnehmer_summe=("teilnehmer","sum"),
                umsatz_beispiel=("umsatz_beispiel","sum"),
                preis_mittel=("preis_euro","mean"))
           .reset_index()
           .sort_values("umsatz_beispiel", ascending=False)
)

print("\nRANKING (alle):")
print(ranking)

print("\nTOP 3:")
print(ranking.head(3))

# ===== 5) Pivot (LZ3) =====
pivot = pd.pivot_table(
    termine,
    index="standort",
    columns="format",
    values="umsatz_beispiel",
    aggfunc="sum",
    fill_value=0
)
print("\nPIVOT (Umsatz je Standort/Format):")
print(pivot)

# ===== 6) Merge (LZ4) =====
standorte = pd.DataFrame([
    {"standort":"Hamburg","region":"Nord"},
    {"standort":"Berlin","region":"Ost"},
    {"standort":"Muenchen","region":"Sued"},
    {"standort":"Koeln","region":"West"},
])

ranking_mit_region = ranking.merge(standorte, on="standort", how="left")
print("\nRANKING + REGION:")
print(ranking_mit_region)

# ===== Bonus: Plot (optional) =====
# import matplotlib.pyplot as plt
# ax = ranking.set_index("standort")["umsatz_beispiel"].plot(kind="bar", title="Umsatz (Beispiel) je Standort")
# ax.set_ylabel("EUR")
# plt.tight_layout()
# plt.show()