Der Fahrplan

Das Notebook folgt den sechs Schritten aus Lab 00 – nur dass es die Schritte 2 bis 5 selbst ausführt und Schritt 6 vorbereitet. Es läuft ohne Installation in Colab, weil alle Pakete (pandas, numpy, matplotlib) dort vorhanden sind; nur für die Datenbankzelle installiert es zwei Pakete nach.

1–2Laden, Sichten
3Bereinigen, ableiten
4Kennzahlen
5Vier Auswertungen
6–7Sternschema, Export, Datenbank
8Wo KI hilft

Die Reihenfolge ist zwingend: Abschnitt 4 rechnet mit revenue, das Abschnitt 3 erzeugt; Abschnitt 6 braucht arrival_date, ebenfalls aus Abschnitt 3. Wer eine Zelle überspringt, bekommt einen KeyError – die Meldung sagt, welche Spalte fehlt, und damit, welche Zelle nicht gelaufen ist. Deshalb der Rat aus Lab 02: nach dem Öffnen immer Laufzeit → Alle ausführen.

Abschnitte 1 und 2: Laden und sichten

Die erste Codezelle lädt die Datei per URL (Lab 01) und zeigt df.head(). Die zweite und dritte Zelle sichten: df.info() nennt je Spalte Typ und Zahl der gefüllten Werte, df.describe() Minimum, Maximum, Mittelwert und Quartile. Hier fallen die Eigenheiten aus Lab 01 zum ersten Mal auf – adr mit Maximum 5.400, children mit 119.386 statt 119.390 Werten.

BI_Hotel_Booking_Demand.ipynb – ColabPython 3
[3]
df.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 119390 entries, 0 to 119389 1
Data columns (total 32 columns):
 #   Column                    Non-Null Count   Dtype
 0   hotel                     119390 non-null  str
 1   is_canceled               119390 non-null  int64 2
 …
 10  children                  119386 non-null  float64 3
 …
 27  adr                       119390 non-null  float64
dtypes: float64(4), int64(16), str(12)

Nachbildung der Oberfläche, Stand 09/2026 – Beschriftungen wie im Original; Ausgabe gekürzt.

  1. 1119.390 Zeilen – die Kontrollzahl, die in jedem späteren Artefakt wiederkehrt.
  2. 2is_canceled ist eine ganze Zahl (0/1). Ihr Mittelwert ist die Stornoquote – deshalb bleibt sie eine Zahl und wird nicht zu Text.
  3. 3Vier fehlende Werte in children: 119.386 statt 119.390. Die Spalte ist deshalb float64, obwohl Kinder ganze Zahlen sind – pandas kann fehlende Werte nur in Dezimalspalten halten.

Abschnitt 3: Bereinigen und ableiten

Zwei Zellen. Die erste füllt Lücken, die zweite erzeugt die Spalten, die für Kennzahlen gebraucht werden. Beide treffen Annahmen, und beide schreiben sie hin. Eine Bereinigung, die nur im Code steht, ist nach drei Monaten eine Zahl, die niemand mehr erklären kann.

Drei Annahmen der Bereinigung

  • children fehlt → 0. Annahme: keine Angabe heißt kein Kind. Betrifft vier Zeilen.
  • country fehlt → UNK. Annahme: lieber ein sichtbares „unbekannt“ als eine Zeile, die später aus jedem Join fällt. Betrifft 488 Zeilen.
  • agent, company: der Text „NULL“ → echtes NaN. Neuere pandas-Versionen erkennen den Text schon beim Laden; die Zeilen sichern das für andere Quellen ab.

Vier abgeleitete Spalten

  • arrival_date – aus Jahr, Monatsname und Tag ein echtes Datum; der englische Monatsname wird über ein Wörterbuch zur Zahl.
  • total_nights – Wochenend- plus Wochentagsnächte.
  • total_guests – Erwachsene plus Kinder plus Babys.
  • revenueadr × total_nights: der Zimmerumsatz einer Buchung, nur Übernachtung. Das ist die Spalte, aus der alle drei Umsatzbegriffe des Projekts entstehen.

Abschnitt 4: Kennzahlen

Eine Zelle rechnet den ganzen Katalog: zehn Kennzahlen über alle Buchungen, gesammelt in einer pd.Series. Die Definitionen sind dieselben wie später in der Datenbank, in Power BI und im Dashboard – Lab 06 rechnet sie in SQL nach. Zwei Zeilen unterscheiden sich nur im Filter auf is_canceled: Die Summe von revenue ohne Filter ist der gebuchte Umsatz, mit Filter der stornobereinigte.

KennzahlZeile im NotebookWert
Anzahl Buchungenlen(df)119.390
Stornoquotedf["is_canceled"].mean() * 10037,0 %
Ø Vorlaufzeitdf["lead_time"].mean()104,0 Tage
Ø Aufenthaltsdauerdf["total_nights"].mean()3,43 Nächte
Gebuchte Zimmernächtedf["total_nights"].sum()409.257
Ø Zimmerpreis (ADR)df["adr"].mean()101,83 €
Umsatz (stornobereinigt)df.loc[df["is_canceled"] == 0, "revenue"].sum()25.996.260 €
Gebuchter Umsatzdf["revenue"].sum()42.723.498 €
Wiederholungsgast-Anteildf["is_repeated_guest"].mean() * 1003,2 %
Anteil mit Sonderwünschen(df["total_of_special_requests"] > 0).mean() * 10041,1 %

Der Hinweis im Notebook gilt für jede Auswertung danach: Der Datensatz kennt keine Zimmerkapazität, deshalb gibt es keine Auslastung und keinen RevPAR. Gebuchte Zimmernächte sind der Ersatz – und das steht so dabei.

Abschnitt 5: Vier Auswertungen

Jede Auswertung ist ein groupby plus ein Diagramm mit matplotlib. Die vier Zellen entsprechen den vier Fragestellungen aus Lab 00 – und den vier Seiten des späteren Power-BI-Berichts.

AbschnittGruppierungDiagrammFrage
5.1df.groupby("hotel"): Buchungen, Stornoquote, ADR, Nächtezwei SäulendiagrammeHotels im Vergleich
5.2df.groupby("arrival_date_month").size(), Monate in KalenderreihenfolgeLinieSaisonalität
5.3value_counts() je Vertriebskanal und Marktsegmentzwei BalkendiagrammeVertrieb
5.4pd.cut(lead_time) in sechs Klassen, dann Stornoquote je KlasseSäulenStornorisiko

Die Zelle 5.2 hat einen Fallstrick, den man kennen sollte: groupby("arrival_date_month") sortiert alphabetisch – April, August, December. Die Zeile .reindex(month_order) bringt die Monate in Kalenderreihenfolge. Ohne sie zeigt die Linie eine Saison, die es nicht gibt.

Abschnitte 6 und 7: Sternschema und Export

Eine kleine Funktion make_dim erzeugt aus jeder Merkmalsspalte eine Dimensionstabelle mit laufender Nummer; eine Datumsdimension entsteht aus allen Tagen zwischen dem frühesten und dem spätesten Datum; die Faktentabelle bekommt statt der Texte die Nummern. Das Modell selbst erklärt Lab 04.

Woran man erkennt, dass es geklappt hat

  • dim_hotel hat zwei Zeilen, dim_country 178 (177 Länder plus UNK), dim_date 1.064 Tage.
  • fact_bookings hat weiterhin 119.390 Zeilen – ein Join, der Zeilen verliert oder verdoppelt, wäre hier sichtbar.
  • Keine Nummer in der Faktentabelle ist NaN; sonst gäbe es einen Wert, der in keiner Dimension steht.

Abschnitt 7 schreibt die neun Tabellen als CSV-Dateien ins Colab-Dateisystem. Für die Vorlesung ist dieser Schritt schon getan: Dieselben Dateien liegen im Repository unter data/ und sind mit sql/02_load_data.py in die Datenbank geladen worden – genau die Dateien, die auch diese Lernumgebung in Ihren Browser lädt.

Abschnitt 7.1: Live aus der Datenbank

Die letzte Codezelle verbindet sich mit der fertigen Datenbank und liest die Stornoquote je Hotel per SQL. Das Ergebnis muss mit Abschnitt 5.1 übereinstimmen – 41,7 % und 27,8 %. Tut es das, ist bewiesen, dass Notebook und Datenbank dieselben Daten tragen.

Auch hier steht kein Kennwort im Code: Die Verbindungs-URL kommt aus dem Secrets-Panel von Colab (Lab 02), Name HOTEL_DB_URL; Benutzer und Kennwort der Leserolle stehen im README des Repos. Lab 05 erklärt, was die Rolle darf und was nicht.

Abschnitt 8: Wo KI hilft

Der letzte Abschnitt ist Text: eine Tabelle, an welchen Stellen des Projekts ein KI-Assistent hilft – Spalten erklären, Auffälligkeiten finden, ein Sternschema vorschlagen, Diagrammcode erzeugen, eine Zusammenfassung schreiben. Die Regel dazu steht im Notebook selbst: KI schlägt vor, der Mensch prüft. Ein vorgeschlagenes Sternschema, das agent als Kennzahl führt, ist schnell erzeugt und langsam bemerkt.

Probieren Sie es aus: Lassen Sie sich von einem Assistenten den Code für Abschnitt 5.4 erklären und vergleichen Sie die Erklärung mit der Zelle. Wo die Erklärung eine Zeile auslässt oder erfindet, haben Sie gelernt, warum man prüft.

Übungen

Fünf Übungen: die Reihenfolge der Abschnitte, die Annahmen der Bereinigung, eine Zuordnung von Codezeilen zu Abschnitten, eine Checkliste durch das echte Notebook in Colab und Verständnisfragen zu Sternschema und Datenbankzelle.

Zusammenfassung