data_processor.py aktualisiert
This commit is contained in:
@@ -5504,8 +5504,7 @@ class DataProcessor:
|
|||||||
'Techniker_Mittel (50-249)',
|
'Techniker_Mittel (50-249)',
|
||||||
'Techniker_Gross (250+)']
|
'Techniker_Gross (250+)']
|
||||||
|
|
||||||
df_filtered.loc[:,
|
df_filtered.loc[:, 'Techniker_Bucket'] = pd.cut(df_filtered['Anzahl_Servicetechniker_Numeric'],
|
||||||
'Techniker_Bucket'] = pd.cut(df_filtered['Anzahl_Servicetechniker_Numeric'],
|
|
||||||
bins=bins_new,
|
bins=bins_new,
|
||||||
labels=labels_new,
|
labels=labels_new,
|
||||||
right=True,
|
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)}")
|
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) ---
|
# --- 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"
|
branche_col_internal = "branche_ki"
|
||||||
self.logger.info(f"Verarbeite kategoriales Feature '{branche_col_internal}' und mappe es zu 'Branchen_Gruppe'...")
|
self.logger.info(f"Verarbeite kategoriales Feature '{branche_col_internal}' und mappe es zu 'Branchen_Gruppe'...")
|
||||||
|
|
||||||
@@ -5522,8 +5521,7 @@ 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.")
|
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
|
return None
|
||||||
|
|
||||||
# Wende das saubere Mapping aus der Config an. Die Schlüssel sind jetzt lesbar.
|
# Wende das saubere Mapping aus der Config an, um nur den 'gruppe'-String zu extrahieren.
|
||||||
# Wir müssen die Eingabedaten aus dem Sheet NICHT MEHR normalisieren.
|
|
||||||
branch_group_map = {branch_name: details.get('gruppe', 'Sonstige') for branch_name, details in Config.BRANCH_GROUP_MAPPING.items()}
|
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')
|
||||||
|
|
||||||
@@ -5531,75 +5529,44 @@ class DataProcessor:
|
|||||||
self.logger.debug(
|
self.logger.debug(
|
||||||
f"Verteilung der Branchen-Gruppen:\n{df_filtered['Branchen_Gruppe'].value_counts(normalize=True).sort_index().round(3)}")
|
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
|
# --- One-Hot Encoding ---
|
||||||
# durchgeführt
|
df_encoded = pd.get_dummies(df_filtered, columns=['Branchen_Gruppe'], prefix='Gruppe', dummy_na=False)
|
||||||
df_encoded = pd.get_dummies(
|
self.logger.info("One-Hot Encoding fuer 'Branchen_Gruppe' durchgefuehrt.")
|
||||||
df_filtered,
|
|
||||||
columns=['Branchen_Gruppe'],
|
|
||||||
prefix='Gruppe',
|
|
||||||
dummy_na=False)
|
|
||||||
self.logger.info(
|
|
||||||
f"One-Hot Encoding fuer 'Branchen_Gruppe' durchgefuehrt.")
|
|
||||||
|
|
||||||
# --- Finale Auswahl der Features fuer das Modell ---
|
# --- Finale Auswahl der Features fuer das Modell ---
|
||||||
feature_columns_ml = [
|
feature_columns_ml = [col for col in df_encoded.columns if col.startswith('Gruppe_')]
|
||||||
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'])
|
||||||
feature_columns_ml.extend([
|
self.logger.info(f"Finale Feature-Auswahl für das Training: {feature_columns_ml}")
|
||||||
'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'
|
target_column_ml = 'Techniker_Bucket'
|
||||||
identification_cols_ml = ['name', 'Anzahl_Servicetechniker_Numeric']
|
identification_cols_ml = ['name', 'Anzahl_Servicetechniker_Numeric']
|
||||||
|
|
||||||
final_cols_for_df_ml = identification_cols_ml + \
|
final_cols_for_df_ml = identification_cols_ml + feature_columns_ml + [target_column_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]
|
||||||
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:
|
if missing_final_cols_ml:
|
||||||
self.logger.critical(
|
self.logger.critical(f"FEHLER: Finale Spalten fuer Modellierung fehlen im DataFrame: {missing_final_cols_ml}")
|
||||||
f"FEHLER: Finale Spalten fuer Modellierung fehlen im DataFrame: {missing_final_cols_ml}")
|
|
||||||
return None
|
return None
|
||||||
|
|
||||||
df_model_ready = df_encoded[final_cols_for_df_ml].copy()
|
df_model_ready = df_encoded[final_cols_for_df_ml].copy()
|
||||||
|
|
||||||
numeric_features_to_convert = [
|
numeric_features_to_convert = ['Log_Finaler_Umsatz_ML', 'Log_Finaler_Mitarbeiter_ML', 'Umsatz_pro_MA_ML', 'Anzahl_Servicetechniker_Numeric']
|
||||||
'Log_Finaler_Umsatz_ML',
|
|
||||||
'Log_Finaler_Mitarbeiter_ML',
|
|
||||||
'Umsatz_pro_MA_ML',
|
|
||||||
'Anzahl_Servicetechniker_Numeric']
|
|
||||||
for col in numeric_features_to_convert:
|
for col in numeric_features_to_convert:
|
||||||
if col in df_model_ready.columns:
|
if col in df_model_ready.columns:
|
||||||
df_model_ready[col] = pd.to_numeric(
|
df_model_ready[col] = pd.to_numeric(df_model_ready[col], errors='coerce')
|
||||||
df_model_ready[col], errors='coerce')
|
|
||||||
|
|
||||||
df_model_ready = df_model_ready.reset_index(drop=True)
|
df_model_ready = df_model_ready.reset_index(drop=True)
|
||||||
|
|
||||||
self.logger.info(
|
self.logger.info("Datenvorbereitung fuer Modellierung (Training) abgeschlossen.")
|
||||||
"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"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)}")
|
self.logger.info(f"Anzahl Feature-Spalten: {len(feature_columns_ml)}")
|
||||||
|
|
||||||
numeric_features_for_imputation_ml = [
|
numeric_features_for_imputation_ml = ['Log_Finaler_Umsatz_ML', 'Log_Finaler_Mitarbeiter_ML', 'Umsatz_pro_MA_ML']
|
||||||
'Log_Finaler_Umsatz_ML',
|
existing_numeric_features = [col for col in numeric_features_for_imputation_ml if col in df_model_ready.columns]
|
||||||
'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:
|
if existing_numeric_features:
|
||||||
nan_counts = df_model_ready[existing_numeric_features].isna().sum()
|
nan_counts = df_model_ready[existing_numeric_features].isna().sum()
|
||||||
self.logger.info(
|
self.logger.info(f"Fehlende Werte in numerischen Features vor Imputation:\n{nan_counts}")
|
||||||
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()
|
||||||
rows_with_nan = df_model_ready[existing_numeric_features].isna().any(
|
self.logger.info(f"Anzahl Zeilen mit mindestens einem fehlenden numerischen Feature (vor Imputation): {rows_with_nan}")
|
||||||
axis=1).sum()
|
|
||||||
self.logger.info(
|
|
||||||
f"Anzahl Zeilen mit mindestens einem fehlenden numerischen Feature (vor Imputation): {rows_with_nan}")
|
|
||||||
|
|
||||||
return df_model_ready
|
return df_model_ready
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user