💡 Tipp: Der Code hinter diesen Analysen kann mit dem Schalter oben rechts ein- und ausgeblendet werden
Titel: Weihnachtsmärkte München Description: Interaktive Karte der Münchner Weihnachtsmärkte - finde heraus, welche Märkte heute geöffnet haben Dataset: https://opendata.muenchen.de/dataset/92515550-b236-4a08-9259-260513889548/ Landing: true
Weihnachtsmärkte in München¶
Interaktive Karte¶
München verwandelt sich in der Adventszeit in ein winterliches Wunderland mit zahlreichen Weihnachtsmärkten. Vom traditionellen Weihnachtsmarkt am Marienplatz bis zu kleineren, versteckten Christkindlmärkten in verschiedenen Stadtvierteln.
Hier findest du:
- Alle touristisch relevanten Weihnachtsmärkte Münchens auf einer Karte
- Einen Slider mit dem du ein Datum auswählen und sofort erkennen kannst, welche Märkte an diesem Tag geöffnet haben
- Märkte, die offen haben werden grün dargestellt, geschlossene rot.
- Klicke auf den Punkt für jeden Markt, für mehr Details
Die Daten stammen vom Referat für Arbeit und Wirtschaft (RAW) der Landeshauptstadt München.
In [1]:
import pandas as pd
import plotly.graph_objects as go
from plotly.offline import plot, iplot, init_notebook_mode
from datetime import date
import warnings
import locale
import sys
warnings.filterwarnings('ignore')
# Versuche deutsche Locale zu setzen für Datumsformatierung
try:
locale.setlocale(locale.LC_TIME, 'de_DE.UTF-8')
except:
try:
locale.setlocale(locale.LC_TIME, 'German_Germany')
except:
pass # Falls keine deutsche Locale verfügbar ist, verwenden wir das manuelle Dictionary
# Plotly für Notebook initialisieren
try:
init_notebook_mode(connected=True)
except:
pass
# Deutsche Monatsnamen für die Datumsformatierung
MONATE = {
1: 'Januar', 2: 'Februar', 3: 'März', 4: 'April',
5: 'Mai', 6: 'Juni', 7: 'Juli', 8: 'August',
9: 'September', 10: 'Oktober', 11: 'November', 12: 'Dezember'
}
# Dataset laden und vorbereiten - mit robuster Fehlerbehandlung
csv_urls = [
"https://opendata.muenchen.de/dataset/92515550-b236-4a08-9259-260513889548/resource/312260ca-7346-4b85-a357-3764bcadc6dd/download/weihnachtsmaerkte.csv",
"https://opendata.muenchen.de/dataset/92515550-b236-4a08-9259-260513889548/resource/312260ca-7346-4b85-a357-3764bcadc6dd/download"
]
df = None
last_error = None
for url in csv_urls:
try:
df = pd.read_csv(url, storage_options={'timeout': 10})
break
except Exception as e:
last_error = e
continue
# Wenn keine Daten geladen werden konnten, zeige eine Nachricht und beende
if df is None:
print("\n" + "="*60)
print("❌ FEHLER: Die Weihnachtsmarkt-Daten konnten nicht geladen werden.")
print("="*60)
print("\nDie München Open Data API ist momentan nicht verfügbar.")
print("Mögliche Ursachen:")
print("- Der Server ist temporär offline (Status 503)")
print("- Wartungsarbeiten am Open Data Portal")
print("- Netzwerkprobleme")
print("\nBitte versuchen Sie es später erneut oder prüfen Sie:")
print("https://opendata.muenchen.de/")
print("\nLetzter Fehler:", str(last_error))
# Stoppe die Ausführung hier
raise SystemExit("Daten konnten nicht geladen werden - Notebook-Ausführung beendet.")
# Clean column names - remove any trailing/leading spaces
df.columns = df.columns.str.strip()
# Smart coordinate handling - detect if already decimal or needs conversion
if df['latitude'].iloc[0] < 100:
# Already in decimal format (48.xxxxx, 11.xxxxx)
# No conversion needed, coordinates are already correct
pass
else:
# Integer format needs conversion
df['latitude'] = df['latitude'].astype(str).str.replace('.', '', n=2).astype(float) / 1000000
df['longitude'] = df['longitude'].astype(str).str.replace('.', '', n=2).astype(float) / 1000000
df['startdatum'] = pd.to_datetime(df['startdatum'], format='%d.%m.%Y', dayfirst=True)
df['enddatum'] = pd.to_datetime(df['enddatum'], format='%d.%m.%Y', dayfirst=True)
# Datums-Range anpassen: vom ersten Markttag bis maximal 6. Januar
start_date = df['startdatum'].min()
end_date_max = pd.Timestamp(date(2026, 1, 6)) # 6. Januar (Dreikönigstag)
end_date = min(df['enddatum'].max(), end_date_max) # Nehme das frühere Datum
date_range = pd.date_range(start=start_date, end=end_date, freq='D')
FEIERTAGE = {date(2025, 12, 25), date(2025, 12, 26), date(2026, 1, 1), date(2026, 1, 6)}
# Wichtige Daten für Buttons definieren
WICHTIGE_DATEN = {
'1. Advent': date(2025, 11, 30),
'2. Advent': date(2025, 12, 7),
'3. Advent': date(2025, 12, 14),
'4. Advent': date(2025, 12, 21),
'Heiligabend': date(2025, 12, 24),
'Silvester': date(2025, 12, 31),
'Neujahr': date(2026, 1, 1),
'Dreikönig': date(2026, 1, 6)
}
# Wochentage auf Deutsch
WOCHENTAGE = ['Montag', 'Dienstag', 'Mittwoch', 'Donnerstag', 'Freitag', 'Samstag', 'Sonntag']
def ist_markt_geoeffnet(row, selected_date):
if not (row['startdatum'].date() <= selected_date <= row['enddatum'].date()):
return False
anmerkungen = str(row['datum_anmerkungen']).lower() if pd.notna(row['datum_anmerkungen']) else ''
weekday = selected_date.weekday()
if '24.12' in anmerkungen and selected_date == date(2025, 12, 24):
return False
if 'bis 23.12' in anmerkungen and selected_date > date(2025, 12, 23):
return False
if 'sonn' in anmerkungen and 'feiertag' in anmerkungen and 'geschlossen' in anmerkungen and (weekday == 6 or selected_date in FEIERTAGE):
return False
if 'nur' in anmerkungen and 'samstag' in anmerkungen and 'sonntag' in anmerkungen and weekday not in [5, 6]:
return False
if 'donnerstag bis sonntag' in anmerkungen and weekday not in [3, 4, 5, 6]:
return False
return True
def create_trace_for_date(selected_date):
df_copy = df.copy()
df_copy['ist_offen'] = df_copy.apply(lambda row: ist_markt_geoeffnet(row, selected_date), axis=1)
# OPTIMIERT: Kürzere Hover-Texte für weniger Verdeckung
hover_texts = []
for _, row in df_copy.iterrows():
status = "Geöffnet" if row['ist_offen'] else "Geschlossen"
# Kompakter Text ohne lange Beschreibungen
text = f"<b>{row['marktname']}</b><br>"
text += f"<b>{status}</b><br>"
text += f"{row['adresse']}<br>"
text += f"{row['startdatum'].strftime('%d.%m.')}-{row['enddatum'].strftime('%d.%m.')}"
# Nur kurze Anmerkung wenn vorhanden
if pd.notna(row['datum_anmerkungen']) and len(str(row['datum_anmerkungen'])) < 50:
text += f"<br><i>{row['datum_anmerkungen']}</i>"
hover_texts.append(text)
return go.Scattermapbox(
lat=df_copy['latitude'],
lon=df_copy['longitude'],
mode='markers',
marker=dict(
size=16, # OPTIMIERT: Größere Marker (von 14 auf 16)
color=['#10b981' if x else '#ef4444' for x in df_copy['ist_offen']],
opacity=1.0 # OPTIMIERT: Volle Deckkraft (von 0.9 auf 1.0)
# Hinweis: Scattermapbox unterstützt keine Marker-Ränder
),
text=hover_texts,
hovertemplate='%{text}<extra></extra>'
), df_copy['ist_offen'].sum(), len(df_copy) - df_copy['ist_offen'].sum()
def format_date_title(selected_date):
"""Formatiert das Datum mit Wochentag für bessere Verständlichkeit - komplett auf Deutsch"""
weekday = WOCHENTAGE[selected_date.weekday()]
# Verwende deutsches Monatsformat
monat = MONATE[selected_date.month]
return f"{weekday}, {selected_date.day}. {monat} {selected_date.year}"
# Startdatum: Heute (falls innerhalb des Zeitraums, sonst erster Markttag)
today = pd.Timestamp.now().date()
if today >= start_date.date() and today <= end_date.date():
initial_date = today
# Finde den Index für heute im date_range
initial_index = (pd.Timestamp(today) - start_date).days
else:
# Falls heute außerhalb des Zeitraums, verwende den ersten Markttag
initial_date = start_date.date()
initial_index = 0
# Frames erstellen mit Slider-Updates
frames = []
for i, selected_date in enumerate(date_range):
trace, offen, geschlossen = create_trace_for_date(selected_date.date())
frames.append(go.Frame(
data=[trace],
name=selected_date.strftime('%Y-%m-%d'),
layout=go.Layout(
title=dict(
text=f"<b style='font-size: 22px; color: #111827;'>Weihnachtsmärkte München</b><br><span style='font-size: 16px; color: #111827;'>{format_date_title(selected_date.date())}</span><br><span style='font-size: 13px; color: #111827;'><span style='color: #10b981;'>●</span> {offen} geöffnet <span style='color: #ef4444;'>●</span> {geschlossen} geschlossen</span>",
x=0.5, xanchor='center'
),
sliders=[{
'active': i, # Update slider position with frame
'yanchor': 'top', 'y': 0.05, 'xanchor': 'center', 'x': 0.5,
'transition': {'duration': 0},
'pad': {'b': 10, 't': 50},
'len': 0.85,
'bgcolor': '#f9fafb', 'bordercolor': '#d1d5db', 'borderwidth': 1,
'ticklen': 5, 'tickwidth': 1, 'tickcolor': '#9ca3af', 'minorticklen': 0,
'steps': [] # Steps will be added later
}]
)
))
initial_trace, initial_offen, initial_geschlossen = create_trace_for_date(initial_date)
fig = go.Figure(data=[initial_trace], frames=frames)
# Slider-Schritte mit sichtbaren Labels erstellen (nur Daten, keine Namen)
slider_steps = []
for i, d in enumerate(date_range):
# Label nur jeden 7. Tag anzeigen (nur Datum, keine speziellen Namen)
if i % 7 == 0:
label = d.strftime('%d.%m.')
else:
label = ''
slider_steps.append({
'args': [[d.strftime('%Y-%m-%d')], {
'frame': {'duration': 0, 'redraw': True},
'mode': 'immediate',
'transition': {'duration': 0}
}],
'label': label,
'method': 'animate'
})
# Schnellzugriff-Buttons erstellen
buttons = []
for name, datum in WICHTIGE_DATEN.items():
# Nur Buttons für Daten innerhalb des Zeitraums hinzufügen
if datum >= date_range[0].date() and datum <= date_range[-1].date():
buttons.append({
'label': name,
'method': 'animate',
'args': [[datum.strftime('%Y-%m-%d')], {
'frame': {'duration': 0, 'redraw': True},
'mode': 'immediate',
'transition': {'duration': 0}
}]
})
fig.update_layout(
mapbox=dict(style='carto-positron', center=dict(lat=48.15, lon=11.57), zoom=10.8),
showlegend=False,
height=850,
margin=dict(l=0, r=0, t=120, b=250),
paper_bgcolor='rgba(0,0,0,0)',
plot_bgcolor='rgba(0,0,0,0)',
title=dict(
text=f"<b style='font-size: 22px; color: #111827;'>Weihnachtsmärkte München</b><br><span style='font-size: 16px; color: #111827;'>{format_date_title(initial_date)}</span><br><span style='font-size: 13px; color: #111827;'><span style='color: #10b981;'>●</span> {initial_offen} geöffnet <span style='color: #ef4444;'>●</span> {initial_geschlossen} geschlossen</span>",
x=0.5, xanchor='center'
),
sliders=[{
'active': initial_index,
'yanchor': 'top', 'y': 0.05, 'xanchor': 'center', 'x': 0.5,
'transition': {'duration': 0},
'pad': {'b': 10, 't': 50},
'len': 0.85,
'bgcolor': '#f9fafb', 'bordercolor': '#d1d5db', 'borderwidth': 1,
'ticklen': 5, 'tickwidth': 1, 'tickcolor': '#9ca3af', 'minorticklen': 0,
'steps': slider_steps
}],
updatemenus=[{
'buttons': buttons,
'direction': 'left',
'pad': {'r': 10, 't': 10},
'showactive': True,
'type': 'buttons',
'x': 0.5,
'xanchor': 'center',
'y': -0.25,
'yanchor': 'top',
'bgcolor': '#f9fafb',
'bordercolor': '#d1d5db',
'borderwidth': 1,
'font': {'size': 12}
}],
# OPTIMIERT: Transparente, kleinere Tooltips
hoverlabel=dict(
bgcolor='rgba(255, 255, 255, 0.90)', # OPTIMIERT: Leicht transparent (von opak zu 90% transparent)
font_size=11, # OPTIMIERT: Kleinere Schrift (von 13 auf 11)
font_family='-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif',
font_color='black',
align='left', # NEU: Linksbündiger Text für kompaktere Darstellung
namelength=-1 # NEU: Kein Abschneiden von Namen
),
hovermode='closest', # OPTIMIERT: Nur der nächste Punkt wird angezeigt
hoverdistance=15 # OPTIMIERT: Kleinerer Aktivierungsbereich (Standard: 20)
)
# Für Jupyter Notebook und HTML-Export
from IPython.display import HTML
# Graph als HTML mit eingebettetem Plotly generieren
html_str = fig.to_html(include_plotlyjs='cdn', config={'displayModeBar': False})
# In Jupyter anzeigen
try:
from IPython.display import display
display(HTML(html_str))
except:
# Fallback für normale Anzeige
fig.show(config={'displayModeBar': False})
Vollständige Marktübersicht¶
Alle Weihnachtsmärkte mit detaillierten Informationen:
In [2]:
# Übersichtstabelle aller Märkte erstellen
import pandas as pd
from IPython.display import display, HTML
# DataFrame für Anzeige vorbereiten
df_display = df.copy()
# Spalten umbenennen und formatieren
df_display['Von'] = df_display['startdatum'].dt.strftime('%d.%m.%Y')
df_display['Bis'] = df_display['enddatum'].dt.strftime('%d.%m.%Y')
df_display['Dauer (Tage)'] = (df_display['enddatum'] - df_display['startdatum']).dt.days + 1
# Beschreibung kürzen für bessere Übersicht
df_display['Beschreibung_kurz'] = df_display['beschreibung'].apply(
lambda x: str(x)[:100] + '...' if pd.notna(x) and len(str(x)) > 100 else str(x) if pd.notna(x) else ''
)
# Website als klickbarer Link
def make_clickable(url):
if pd.notna(url) and url != 'nan':
return f'<a href="{url}" target="_blank">Link</a>'
return ''
df_display['Website_Link'] = df_display['website'].apply(make_clickable)
# Relevante Spalten auswählen
columns_to_show = [
'marktname',
'adresse',
'Von',
'Bis',
'Dauer (Tage)',
'datum_anmerkungen',
'Beschreibung_kurz',
'Website_Link'
]
# Spaltennamen für Anzeige
column_names = {
'marktname': 'Marktname',
'adresse': 'Adresse',
'Von': 'Von',
'Bis': 'Bis',
'Dauer (Tage)': 'Dauer',
'datum_anmerkungen': 'Öffnungszeiten',
'Beschreibung_kurz': 'Beschreibung',
'Website_Link': 'Website'
}
# Nach Startdatum sortieren
df_display = df_display.sort_values('startdatum')
# Tabelle stylen
styled_table = df_display[columns_to_show].rename(columns=column_names).style\
.set_properties(**{
'text-align': 'left',
'font-size': '12px',
'padding': '8px'
})\
.set_table_styles([
{'selector': 'th', 'props': [
('background-color', '#f3f4f6'),
('color', '#111827'),
('font-weight', 'bold'),
('text-align', 'left'),
('padding', '10px'),
('border-bottom', '2px solid #d1d5db')
]},
{'selector': 'tr:nth-of-type(even)', 'props': [
('background-color', '#f9fafb')
]},
{'selector': 'tr:hover', 'props': [
('background-color', '#e5e7eb')
]}
])\
.hide(axis='index')
# HTML rendern und anzeigen
html = styled_table.to_html(escape=False)
display(HTML(html))
print(f"\n Gesamt: {len(df_display)} Weihnachtsmärkte")
| Marktname | Adresse | Von | Bis | Dauer | Öffnungszeiten | Beschreibung | Website |
|---|---|---|---|---|---|---|---|
| Winterworld Motorworld | Motorworld | 07.11.2025 | 28.12.2025 | 52 | Ein aufregender Weihnachtsmarkt mit einer Eislaufbahn und Livemusik in historischem Ambiente. ... | Link | |
| Weihnachts- und Wintermarkt am Flughafen München | München Flughafen | 13.11.2025 | 28.12.2025 | 46 | Ein festlicher Markt im Tannenwald mit Live-Musik und kulinarischen Schmankerln. ... | Link | |
| Zauberhafter Weihnachtsmarkt im Werksviertel | Knödelplatz | 13.11.2025 | 21.12.2025 | 39 | Ein kreativer Markt mit vielfältigem Bühnenprogramm und Foodtrucks. ... | Link | |
| Glühwein-Festival im Bogenhausener Weihnachtszauberwald | Cosimastraße | 13.11.2025 | 11.01.2026 | 60 | Ein zauberhafter Weihnachtsmarkt mit vielen Glühweinsorten und internationaler Küche. ... | Link | |
| Winterrausch im Hexenhaus | Pilgersheimerstraße 13 | 14.11.2025 | 23.12.2025 | 40 | Handwerksmarkt bis 23.12. | Ein gemütlicher Markt mit lokalen Künstlern und einem kreativen Programm. ... | Link |
| Weihnachtsmarkt auf der Praterinsel | Praterinsel 3-4 | 14.11.2025 | 29.12.2025 | 46 | Ein romantischer Markt mit Chillout-Oasen und Street Food direkt am Wasser. ... | Link | |
| Weihnachtsdorf im Kaiserhof der Residenz | Residenzstraße 1 | 17.11.2025 | 22.12.2025 | 36 | Ein idyllisches Weihnachtsdorf im Innenhof der Residenz mit Handwerksständen und Kinderunterhaltung.... | Link | |
| Moosacher Hüttenzauber | Moosacher St.-Martins-Platz | 17.11.2025 | 22.12.2025 | 36 | Der Moosacher Hüttenzauber, ein romantischer Weihnachtsmarkt in München, begeistert seit 2014 jährli... | Link | |
| Weihnachtsmarkt am Chinesischen Turm | Englischer Garten | 20.11.2025 | 23.12.2025 | 34 | Ein traditioneller Markt im Englischen Garten mit Kunsthandwerk und Kinderkarussell. ... | Link | |
| Der Mondscheinexpress | Tumblingerstraße 45 | 20.11.2025 | 23.12.2025 | 34 | Ein kreativer Weihnachtsmarkt mit Kunsthandwerk und einem bunten Rahmenprogramm. ... | Link | |
| Winterzauber auf dem Viktualienmarkt | Viktualienmarkt | 21.11.2025 | 05.01.2026 | 46 | Geschlossen an Sonn- und Feiertagen | Ein beliebter Markt, der mit kulinarischen Leckereien und festlicher Beleuchtung begeistert. ... | Link |
| Eiszauber am Karlsplatz-Stachus | Karlsplatz | 21.11.2025 | 11.01.2026 | 52 | Mit Bayerns größter mobiler Eisarena ist dieser Markt ein Highlight für Schlittschuhläufer. ... | Link | |
| Christkindlmarkt unterm Maibaum | Luise-Kiesselbach-Platz 13 | 24.11.2025 | 06.01.2026 | 44 | nicht geöffnet am 24. Dezember 2025 | Der Christkindlmarkt unterm Maibaum bietet ein romantisches Hüttendorf mit Kunsthandwerk, kulinarisc... | Link |
| Münchner Christkindlmarkt am Marienplatz | Marienplatz | 24.11.2025 | 24.12.2025 | 31 | Der traditionelle Markt vor dem Neuen Rathaus bietet altbayerischen Charme und eine große Auswahl an... | Link | |
| Neuhauser Weihnachtsmarkt | Rotkreuzplatz | 24.11.2025 | 23.12.2025 | 30 | Ein familiärer Markt mit einer Vielzahl von handgefertigten Produkten und einem bunten Programm. ... | Link | |
| Pink Christmas | Stephansplatz | 24.11.2025 | 22.12.2025 | 29 | Ein queerer Weihnachtsmarkt, der Vielfalt und Gemeinschaft feiert. ... | Link | |
| Münchner Feuerzangenbowle | Blumenstraße 22 | 24.11.2025 | 06.01.2026 | 44 | Hier wird die berühmte Feuerzangenbowle in einer festlichen Atmosphäre serviert. ... | Link | |
| Münchner Adventsspektakel und Mittelalterlicher Weihnachtsmarkt | Wittelsbacher Platz 6-10 | 24.11.2025 | 23.12.2025 | 30 | Ein Markt, der Geschichte hautnah erlebbar macht mit historischen Ständen und mittelalterlichen Köst... | Link | |
| Christkindlmarkt am Sendlinger Tor | Sendlinger-Tor-Platz | 24.11.2025 | 22.12.2025 | 29 | Ein kleiner, feiner Markt mit internationalem Flair und einem vielfältigen kulinarischen Angebot. ... | Link | |
| Sendlinger Bergweihnacht | Am Harras | 24.11.2025 | 23.12.2025 | 30 | nan | Am Harras, wo Münchens größter Adventskranz steht, wird während der Vorweihnachtszeit täglich die „S... | Link |
| Tollwood – das Winterfestival | Theresienwiese | 25.11.2025 | 23.12.2025 | 29 | Markt bis 23.12. | Ein alternatives Festival mit Bio-Essen und kulturellen Veranstaltungen in einer festlichen Umgebung... | Link |
| Haidhauser Weihnachtsmarkt | Weißenburger Platz | 25.11.2025 | 23.12.2025 | 29 | Ein beschaulicher, familiärer Markt mit live Musik und handgefertigten Produkten. ... | Link | |
| Märchenbazar im Olympiapark | Spiridon-Louis-Ring 100 | 27.11.2025 | 28.12.2025 | 32 | Ein nostalgischer Markt mit Zirkuszelten und einem bunten Programm für Groß und Klein. ... | Link | |
| Sternenflotte auf der Alten Utting | Lagerhausstraße 15 | 27.11.2025 | 23.12.2025 | 27 | Ein einzigartiger Markt auf einem alten Dampfer mit Glühwein und Live-Musik. ... | Link | |
| Die Weihnachtsmacherei in Berg am Laim | Berg-am-Laim-Straße 103 | 27.11.2025 | 20.12.2025 | 24 | geöffnet von Donnerstag bis Sonntag | Der Weihnachtsmarkt im New-Work-Quartier Die Macherei mit vielfältigem Programm mit Eisstockbahnen ... | Link |
| Schwabinger Weihnachtsmarkt | Münchner Freiheit | 28.11.2025 | 24.12.2025 | 27 | Ein kreativer Markt mit Kunstzelt und vielfältigen kulinarischen Genüssen. ... | Link | |
| Winterzauber Gans am Wasser | Siegenburgerstraße 41 | 28.11.2025 | 01.01.2026 | 35 | geschlossen am 24.12.2025 | Der „Winterzauber Gans am Wasser“ im Westpark ist ein besinnlicher Rückzugsort mit Feuerschalen, Liv... | Link |
| Pasinger Christkindlmarkt | Schererplatz | 29.11.2025 | 21.12.2025 | 23 | nur Samstags und Sonntags geöffnet | Ein traditioneller Markt mit handgefertigten Unikaten und kulinarischen Leckereien. ... | Link |
| Blutenburger Weihnacht | Schloss Blutenburg | 04.12.2025 | 07.12.2025 | 4 | Ein märchenhafter Markt in der idyllischen Kulisse des Schlosses Blutenburg. ... | Link |
Gesamt: 29 Weihnachtsmärkte
Statistiken & Highlights¶
In [3]:
# Statistiken und interessante Fakten
import pandas as pd
import plotly.graph_objects as go
from plotly.subplots import make_subplots
# Basis-Statistiken
print("📊 WEIHNACHTSMARKT-STATISTIKEN 2025/2026\n")
print("=" * 60)
# Zeiträume analysieren
erster_markt = df['startdatum'].min()
letzter_markt = df['enddatum'].max()
print(f"\n📅 ZEITRAUM:")
print(f" Erster Markt öffnet: {erster_markt.strftime('%d.%m.%Y')}")
print(f" Letzter Markt schließt: {letzter_markt.strftime('%d.%m.%Y')}")
# Längster und kürzester Markt
df['dauer'] = (df['enddatum'] - df['startdatum']).dt.days + 1
laengster = df.loc[df['dauer'].idxmax()]
kuerzester = df.loc[df['dauer'].idxmin()]
print(f"\n⏱️ DAUER:")
print(f" Längster Markt: {laengster['marktname']} ({laengster['dauer']} Tage)")
print(f" Kürzester Markt: {kuerzester['marktname']} ({kuerzester['dauer']} Tage)")
print(f" Durchschnittliche Dauer: {df['dauer'].mean():.1f} Tage")
# Besondere Tage analysieren
print(f"\n🎄 BESONDERE TAGE:")
for name, datum in WICHTIGE_DATEN.items():
if datum >= erster_markt.date() and datum <= letzter_markt.date():
df_temp = df.copy()
df_temp['offen'] = df_temp.apply(lambda row: ist_markt_geoeffnet(row, datum), axis=1)
anzahl_offen = df_temp['offen'].sum()
print(f" {name}: {anzahl_offen} Märkte geöffnet")
# Timeline-Visualisierung: Wie viele Märkte haben wann geöffnet?
date_range_stats = pd.date_range(start=erster_markt, end=letzter_markt, freq='D')
open_counts = []
for datum in date_range_stats:
df_temp = df.copy()
df_temp['offen'] = df_temp.apply(lambda row: ist_markt_geoeffnet(row, datum.date()), axis=1)
open_counts.append(df_temp['offen'].sum())
# Timeline-Graph erstellen
fig_timeline = go.Figure()
fig_timeline.add_trace(go.Scatter(
x=date_range_stats,
y=open_counts,
mode='lines',
fill='tozeroy',
line=dict(color='#10b981', width=2),
fillcolor='rgba(16, 185, 129, 0.2)',
name='Anzahl geöffneter Märkte',
hovertemplate='<b>%{x|%d.%m.%Y}</b><br>%{y} Märkte geöffnet<extra></extra>'
))
# Markiere wichtige Tage
for name, datum in WICHTIGE_DATEN.items():
if datum >= erster_markt.date() and datum <= letzter_markt.date():
idx = (datum - erster_markt.date()).days
if idx < len(open_counts):
fig_timeline.add_annotation(
x=datum,
y=open_counts[idx],
text=name,
showarrow=True,
arrowhead=2,
arrowsize=1,
arrowwidth=1,
arrowcolor="#6b7280",
ax=0,
ay=-30,
font=dict(size=10, color="#6b7280")
)
fig_timeline.update_layout(
title="Anzahl geöffneter Weihnachtsmärkte im Zeitverlauf",
xaxis_title="Datum",
yaxis_title="Anzahl geöffneter Märkte",
height=400,
hovermode='x unified',
showlegend=False,
plot_bgcolor='rgba(0,0,0,0)',
paper_bgcolor='rgba(0,0,0,0)',
xaxis=dict(
gridcolor='#e5e7eb',
tickformat='%d.%m.'
),
yaxis=dict(
gridcolor='#e5e7eb',
range=[0, max(open_counts) + 2]
)
)
fig_timeline.show(config={'displayModeBar': False})
# Märkte mit besonderen Features
print(f"\n🌟 BESONDERE MÄRKTE:")
maerkte_mit_website = df[df['website'].notna()].shape[0]
print(f" Märkte mit Website: {maerkte_mit_website} von {len(df)}")
# Märkte mit speziellen Öffnungszeiten
spezielle_oeffnung = df[df['datum_anmerkungen'].notna()].shape[0]
print(f" Märkte mit speziellen Öffnungszeiten: {spezielle_oeffnung}")
# Märkte die auch am Wochenende geöffnet haben
wochenend_maerkte = df[df['datum_anmerkungen'].str.contains('samstag|sonntag', case=False, na=False)].shape[0]
print(f" Märkte mit Wochenend-Hinweis: {wochenend_maerkte}")
📊 WEIHNACHTSMARKT-STATISTIKEN 2025/2026 ============================================================ 📅 ZEITRAUM: Erster Markt öffnet: 07.11.2025 Letzter Markt schließt: 11.01.2026 ⏱️ DAUER: Längster Markt: Glühwein-Festival im Bogenhausener Weihnachtszauberwald (60 Tage) Kürzester Markt: Blutenburger Weihnacht (4 Tage) Durchschnittliche Dauer: 35.1 Tage 🎄 BESONDERE TAGE: 1. Advent: 27 Märkte geöffnet 2. Advent: 28 Märkte geöffnet 3. Advent: 27 Märkte geöffnet 4. Advent: 26 Märkte geöffnet Heiligabend: 11 Märkte geöffnet Silvester: 6 Märkte geöffnet Neujahr: 5 Märkte geöffnet Dreikönig: 4 Märkte geöffnet
🌟 BESONDERE MÄRKTE: Märkte mit Website: 29 von 29 Märkte mit speziellen Öffnungszeiten: 28 Märkte mit Wochenend-Hinweis: 2