data_processor.py aktualisiert

This commit is contained in:
2025-08-04 13:32:19 +00:00
parent 90de1a8e60
commit b2e69d509b

View File

@@ -5504,8 +5504,7 @@ class DataProcessor:
'Techniker_Mittel (50-249)',
'Techniker_Gross (250+)']
df_filtered.loc[:,
'Techniker_Bucket'] = pd.cut(df_filtered['Anzahl_Servicetechniker_Numeric'],
df_filtered.loc[:, 'Techniker_Bucket'] = pd.cut(df_filtered['Anzahl_Servicetechniker_Numeric'],
bins=bins_new,
labels=labels_new,
right=True,
@@ -5514,7 +5513,7 @@ class DataProcessor:
f"Verteilung der neuen Techniker-Buckets:\n{df_filtered['Techniker_Bucket'].value_counts(normalize=True, dropna=False).sort_index().round(3)}")
# --- Kategoriale Features vorbereiten (Branchen-Gruppen) ---
# Dies ist die Spalte mit den Detail-Branchen
# Wir verwenden konsistent die KI-generierte Spalte 'branche_ki' als Basis für die Gruppierung.
branche_col_internal = "branche_ki"
self.logger.info(f"Verarbeite kategoriales Feature '{branche_col_internal}' und mappe es zu 'Branchen_Gruppe'...")
@@ -5522,84 +5521,52 @@ class DataProcessor:
self.logger.critical(f"FEHLER: Die für das Mapping benötigte Spalte '{branche_col_internal}' wurde nicht im DataFrame gefunden. Breche ab.")
return None
# Wende das saubere Mapping aus der Config an. Die Schlüssel sind jetzt lesbar.
# Wir müssen die Eingabedaten aus dem Sheet NICHT MEHR normalisieren.
# Wende das saubere Mapping aus der Config an, um nur den 'gruppe'-String zu extrahieren.
branch_group_map = {branch_name: details.get('gruppe', 'Sonstige') for branch_name, details in Config.BRANCH_GROUP_MAPPING.items()}
df_filtered.loc[:, 'Branchen_Gruppe'] = df_filtered[branche_col_internal].map(branch_group_map).fillna('Sonstige')
df_filtered.loc[:, 'Branchen_Gruppe'] = df_filtered[branche_col_internal].map(branch_group_map).fillna('Sonstige')
self.logger.info("Mapping zu 'Branchen_Gruppe' durchgeführt.")
self.logger.debug(
f"Verteilung der Branchen-Gruppen:\n{df_filtered['Branchen_Gruppe'].value_counts(normalize=True).sort_index().round(3)}")
# One-Hot Encoding wird jetzt auf der neuen 'Branchen_Gruppe'-Spalte
# durchgeführt
df_encoded = pd.get_dummies(
df_filtered,
columns=['Branchen_Gruppe'],
prefix='Gruppe',
dummy_na=False)
self.logger.info(
f"One-Hot Encoding fuer 'Branchen_Gruppe' durchgefuehrt.")
# --- One-Hot Encoding ---
df_encoded = pd.get_dummies(df_filtered, columns=['Branchen_Gruppe'], prefix='Gruppe', dummy_na=False)
self.logger.info("One-Hot Encoding fuer 'Branchen_Gruppe' durchgefuehrt.")
# --- Finale Auswahl der Features fuer das Modell ---
feature_columns_ml = [
col for col in df_encoded.columns if col.startswith('Gruppe_')]
feature_columns_ml.extend([
'Log_Finaler_Umsatz_ML',
'Log_Finaler_Mitarbeiter_ML',
'Umsatz_pro_MA_ML',
'is_part_of_group'
])
self.logger.info(
f"Finale Feature-Auswahl für das Training: {feature_columns_ml}")
feature_columns_ml = [col for col in df_encoded.columns if col.startswith('Gruppe_')]
feature_columns_ml.extend(['Log_Finaler_Umsatz_ML', 'Log_Finaler_Mitarbeiter_ML', 'Umsatz_pro_MA_ML', 'is_part_of_group'])
self.logger.info(f"Finale Feature-Auswahl für das Training: {feature_columns_ml}")
target_column_ml = 'Techniker_Bucket'
identification_cols_ml = ['name', 'Anzahl_Servicetechniker_Numeric']
final_cols_for_df_ml = identification_cols_ml + \
feature_columns_ml + [target_column_ml]
missing_final_cols_ml = [
col for col in final_cols_for_df_ml if col not in df_encoded.columns]
final_cols_for_df_ml = identification_cols_ml + feature_columns_ml + [target_column_ml]
missing_final_cols_ml = [col for col in final_cols_for_df_ml if col not in df_encoded.columns]
if missing_final_cols_ml:
self.logger.critical(
f"FEHLER: Finale Spalten fuer Modellierung fehlen im DataFrame: {missing_final_cols_ml}")
self.logger.critical(f"FEHLER: Finale Spalten fuer Modellierung fehlen im DataFrame: {missing_final_cols_ml}")
return None
df_model_ready = df_encoded[final_cols_for_df_ml].copy()
numeric_features_to_convert = [
'Log_Finaler_Umsatz_ML',
'Log_Finaler_Mitarbeiter_ML',
'Umsatz_pro_MA_ML',
'Anzahl_Servicetechniker_Numeric']
numeric_features_to_convert = ['Log_Finaler_Umsatz_ML', 'Log_Finaler_Mitarbeiter_ML', 'Umsatz_pro_MA_ML', 'Anzahl_Servicetechniker_Numeric']
for col in numeric_features_to_convert:
if col in df_model_ready.columns:
df_model_ready[col] = pd.to_numeric(
df_model_ready[col], errors='coerce')
df_model_ready[col] = pd.to_numeric(df_model_ready[col], errors='coerce')
df_model_ready = df_model_ready.reset_index(drop=True)
self.logger.info(
"Datenvorbereitung fuer Modellierung (Training) abgeschlossen.")
self.logger.info(
f"Finaler DataFrame fuer Modellierung hat {len(df_model_ready)} Zeilen und {len(df_model_ready.columns)} Spalten.")
self.logger.info("Datenvorbereitung fuer Modellierung (Training) abgeschlossen.")
self.logger.info(f"Finaler DataFrame fuer Modellierung hat {len(df_model_ready)} Zeilen und {len(df_model_ready.columns)} Spalten.")
self.logger.info(f"Anzahl Feature-Spalten: {len(feature_columns_ml)}")
numeric_features_for_imputation_ml = [
'Log_Finaler_Umsatz_ML',
'Log_Finaler_Mitarbeiter_ML',
'Umsatz_pro_MA_ML'
]
existing_numeric_features = [
col for col in numeric_features_for_imputation_ml if col in df_model_ready.columns]
numeric_features_for_imputation_ml = ['Log_Finaler_Umsatz_ML', 'Log_Finaler_Mitarbeiter_ML', 'Umsatz_pro_MA_ML']
existing_numeric_features = [col for col in numeric_features_for_imputation_ml if col in df_model_ready.columns]
if existing_numeric_features:
nan_counts = df_model_ready[existing_numeric_features].isna().sum()
self.logger.info(
f"Fehlende Werte in numerischen Features vor Imputation:\n{nan_counts}")
rows_with_nan = df_model_ready[existing_numeric_features].isna().any(
axis=1).sum()
self.logger.info(
f"Anzahl Zeilen mit mindestens einem fehlenden numerischen Feature (vor Imputation): {rows_with_nan}")
self.logger.info(f"Fehlende Werte in numerischen Features vor Imputation:\n{nan_counts}")
rows_with_nan = df_model_ready[existing_numeric_features].isna().any(axis=1).sum()
self.logger.info(f"Anzahl Zeilen mit mindestens einem fehlenden numerischen Feature (vor Imputation): {rows_with_nan}")
return df_model_ready