Python · Fahrer-Datengenerierung
Code
import pandas as pd import numpy as np from datetime import datetime, timedelta np.random.seed(303) # --- Fahrer-Stammdaten --- FAHRER_COUNT = 210 fahrer = [] for i in range(FAHRER_COUNT): alter = np.random.normal(42, 10) betriebszug = np.random.exponential(4.5) # Jahre pendelzeit = np.random.choice([15,25,35,50,70], p=[0.2,0.3,0.25,0.15,0.1]) schichttyp = np.random.choice(['Fernverkehr', 'Nahverkehr', 'Wechselbrücke'], p=[0.45, 0.35, 0.20]) # Fluktuation-Wahrscheinlichkeit: Multi-Faktor-Modell base_churn = 0.12 if betriebszug < 1.5: base_churn += 0.15 # Neue Fahrer gehen häufiger if pendelzeit > 50: base_churn += 0.10 # Langer Pendelweg if alter < 30: base_churn += 0.08 # Jüngere wechseln öfter if schichttyp == 'Fernverkehr': base_churn += 0.06 hat_gekuendigt = np.random.random() < base_churn kuendigung_monat = np.random.randint(6, 24) if hat_gekuendigt else None fahrer.append({ 'fahrer_id': f'F-{i+1:03d}', 'alter': int(np.clip(alter, 21, 64)), 'betriebszugehoerigkeit_j': round(max(0.3, betriebszug), 1), 'pendelzeit_min': pendelzeit, 'schichttyp': schichttyp, 'fuehrerschein_klasse': np.random.choice(['CE', 'C'], p=[0.85,0.15]), 'hat_gekuendigt': hat_gekuendigt, 'kuendigung_monat': kuendigung_monat, }) # --- Monatliche Betriebsdaten pro Fahrer (24 Monate) --- records = [] for f in fahrer: for monat in range(1, 25): # Vorher-Signal: 3 Monate vor Kündigung ändern sich Muster vor_kuendigung = (f['hat_gekuendigt'] and f['kuendigung_monat'] - monat <= 3 and f['kuendigung_monat'] - monat >= 0) ueberstunden = np.random.normal(18, 8) kranktage = np.random.poisson(0.8) wochenend_schichten = np.random.poisson(2.5) mehrtagestouren = np.random.poisson(4) if f['schichttyp'] == 'Fernverkehr' else 0 beschwerden = 0 # --- Signals vor Kündigung --- if vor_kuendigung: kranktage += np.random.poisson(1.5) # Mehr Krankmeldungen ueberstunden -= np.random.uniform(3,8) # Weniger Bereitschaft beschwerden += np.random.choice([0,1,1,2]) # Fahrverhalten aus Telematik harshbraking = np.random.poisson(12) geschw_verstoesse = np.random.poisson(3) if vor_kuendigung: harshbraking += np.random.poisson(5) # Unachtsamkeit steigt geschw_verstoesse += np.random.poisson(2) is_target_month = (f['hat_gekuendigt'] and monat == f['kuendigung_monat']) records.append({ 'fahrer_id': f['fahrer_id'], 'monat': monat, 'alter': f['alter'], 'betriebszug_j': f['betriebszugehoerigkeit_j'], 'pendelzeit_min': f['pendelzeit_min'], 'schichttyp': f['schichttyp'], 'ueberstunden': round(max(0, ueberstunden), 1), 'kranktage': kranktage, 'wochenend_schichten': wochenend_schichten, 'mehrtagestouren': mehrtagestouren, 'beschwerden': beschwerden, 'harshbraking_events': harshbraking, 'geschw_verstoesse': geschw_verstoesse, 'kuendigung': 1 if is_target_month else 0, }) df = pd.DataFrame(records) churn_rate = df.groupby('fahrer_id')['kuendigung'].max().mean() print(f"Dataset: {len(df):,} Monatsdatensätze, {FAHRER_COUNT} Fahrer") print(f"Fluktuation: {churn_rate*100:.1f}% über 24 Monate")