bugfix
This commit is contained in:
@@ -810,7 +810,7 @@ def extract_numeric_value(raw_value, is_umsatz=False):
|
||||
# Globale Funktion (ersetzen Sie Ihre bestehende Version)
|
||||
# Globale Funktion (ersetzen Sie Ihre bestehende Version)
|
||||
def get_numeric_filter_value(value_str, is_umsatz=False):
|
||||
logger = logging.getLogger(__name__ + ".get_numeric_filter_value")
|
||||
logger = logging.getLogger(__name__ + ".get_numeric_filter_value") # Spezifischerer Logger-Name
|
||||
if value_str is None or pd.isna(value_str) or str(value_str).strip() == '':
|
||||
return 0.0 if is_umsatz else 0
|
||||
|
||||
@@ -820,60 +820,75 @@ def get_numeric_filter_value(value_str, is_umsatz=False):
|
||||
return 0.0 if is_umsatz else 0
|
||||
|
||||
try:
|
||||
# Schritt 1: Grundlegende Textbereinigung
|
||||
processed_value = clean_text(raw_value_str_original)
|
||||
if processed_value.lower() in ['k.a.', 'n/a', '-']:
|
||||
return 0.0 if is_umsatz else 0
|
||||
|
||||
# Schritt 2: Präfixe, Suffixe, Währungssymbole und Spannen entfernen
|
||||
processed_value = re.sub(r'(?i)^\s*(ca\.?|circa|rund|etwa|ueber|unter|mehr als|weniger als|bis zu)\s+', '', processed_value)
|
||||
processed_value = re.sub(r'[€$£¥]', '', processed_value).strip()
|
||||
processed_value = re.split(r'\s*(-|–|bis)\s*', processed_value, 1)[0].strip()
|
||||
|
||||
num_extraction_str = processed_value.replace("'", "").replace(" ", "")
|
||||
# Schritt 3: Klammerinhalte entfernen (z.B. Jahreszahlen)
|
||||
num_extraction_str = re.sub(r'\(.*?\)', '', processed_value).strip()
|
||||
|
||||
# Schritt 4: Apostrophe und Leerzeichen zwischen Ziffern entfernen
|
||||
num_extraction_str = num_extraction_str.replace("'", "")
|
||||
num_extraction_str = re.sub(r'(?<=\d)\s+(?=\d)', '', num_extraction_str) # Entfernt Leerzeichen nur zwischen Ziffern
|
||||
|
||||
if not num_extraction_str: return 0.0 if is_umsatz else 0
|
||||
|
||||
# Schritt 5: Punkte und Kommas als Tausender-/Dezimaltrennzeichen standardisieren
|
||||
has_dot = '.' in num_extraction_str
|
||||
has_comma = ',' in num_extraction_str
|
||||
|
||||
if has_dot and has_comma:
|
||||
if num_extraction_str.rfind('.') > num_extraction_str.rfind(','): # US: 1,234.56
|
||||
num_extraction_str = num_extraction_str.replace(',', '')
|
||||
else: # EU: 1.234,56
|
||||
num_extraction_str = num_extraction_str.replace('.', '').replace(',', '.')
|
||||
if num_extraction_str.rfind('.') > num_extraction_str.rfind(','): # US-Stil: 1,234.56
|
||||
num_extraction_str = num_extraction_str.replace(',', '') # Kommas als Tausendertrenner entfernen
|
||||
else: # EU-Stil: 1.234,56
|
||||
num_extraction_str = num_extraction_str.replace('.', '') # Punkte als Tausendertrenner entfernen
|
||||
num_extraction_str = num_extraction_str.replace(',', '.') # Komma zu Dezimalpunkt
|
||||
elif has_comma: # Nur Kommas
|
||||
if num_extraction_str.count(',') == 1 and re.search(r',\d{1,2}$', num_extraction_str) and not re.search(r',\d{3}', num_extraction_str):
|
||||
num_extraction_str = num_extraction_str.replace(',', '.') # Dezimalkomma
|
||||
else: # Tausenderkommas
|
||||
# Wenn ein einzelnes Komma wahrscheinlich ein Dezimaltrennzeichen ist (z.B. "123,45")
|
||||
if num_extraction_str.count(',') == 1 and re.search(r',\d{1,2}$', num_extraction_str) and not re.search(r',\d{3}(,|\s|\Z)', num_extraction_str):
|
||||
num_extraction_str = num_extraction_str.replace(',', '.')
|
||||
else: # Ansonsten sind Kommas Tausendertrenner
|
||||
num_extraction_str = num_extraction_str.replace(',', '')
|
||||
elif has_dot: # Nur Punkte
|
||||
if num_extraction_str.count('.') == 1 and re.search(r'\.\d{1,2}$', num_extraction_str) and not re.search(r'\.\d{3}', num_extraction_str):
|
||||
pass # Dezimalpunkt, bleibt
|
||||
else: # Tausenderpunkte
|
||||
# Wenn ein einzelner Punkt wahrscheinlich ein Dezimaltrennzeichen ist (z.B. "123.45")
|
||||
if num_extraction_str.count('.') == 1 and re.search(r'\.\d{1,2}$', num_extraction_str) and not re.search(r'\.\d{3}(?!\d)', num_extraction_str): # (?!\d) stellt sicher, dass nicht .000 Teil einer größeren Zahl ist
|
||||
pass # Punkt ist Dezimal, bleibt
|
||||
else: # Ansonsten sind Punkte Tausendertrenner
|
||||
num_extraction_str = num_extraction_str.replace('.', '')
|
||||
|
||||
# Finale Validierung mit Regex, ob es eine gültige Zahl ist
|
||||
if not re.fullmatch(r'-?\d+(\.\d+)?', num_extraction_str):
|
||||
# Schritt 6: Finale Validierung und Konvertierung zu float
|
||||
if not re.fullmatch(r'-?\d+(\.\d+)?', num_extraction_str): # Prüft ob String eine gültige Zahl ist
|
||||
logger.debug(f"Kein gültiger numerischer String nach Trennzeichenbehandlung: '{num_extraction_str}' (Original: '{raw_value_str_original}')")
|
||||
return 0.0 if is_umsatz else 0
|
||||
|
||||
num_as_float = float(num_extraction_str)
|
||||
|
||||
# Schritt 7: Einheiten-Skalierung
|
||||
scaled_num = num_as_float
|
||||
original_lower = raw_value_str_original.lower()
|
||||
|
||||
if is_umsatz:
|
||||
if is_umsatz: # Zielwert soll in Millionen sein
|
||||
if re.search(r'\bmrd\s*\b|\bmilliarden\s*\b|\bbillion\s*\b', original_lower):
|
||||
scaled_num = num_as_float * 1000.0
|
||||
scaled_num = num_as_float * 1000.0
|
||||
elif re.search(r'\btsd\s*\b|\btausend\s*\b', original_lower):
|
||||
scaled_num = num_as_float / 1000.0
|
||||
else: # Mitarbeiter
|
||||
scaled_num = num_as_float / 1000.0
|
||||
# Ansonsten: num_as_float wird als bereits in Mio. € interpretiert (da CRM-Umsatz so definiert ist)
|
||||
else: # Mitarbeiter (absolute Zahl)
|
||||
if re.search(r'\bmrd\s*\b|\bmilliarden\s*\b|\bbillion\s*\b', original_lower): scaled_num = num_as_float * 1000000000.0
|
||||
elif re.search(r'\bmio\s*\b|\bmillionen\s*\b|\bmill[.]?\s*\b', original_lower): scaled_num = num_as_float * 1000000.0
|
||||
elif re.search(r'\btsd\s*\b|\btausend\s*\b', original_lower): scaled_num = num_as_float * 1000.0
|
||||
|
||||
# Für Filterlogik nur positive Werte, sonst 0
|
||||
return scaled_num if scaled_num > 0 else (0.0 if is_umsatz else 0)
|
||||
|
||||
except ValueError as e:
|
||||
logger.debug(f"ValueError '{e}' bei Konvertierung (get_numeric_filter_value) von '{num_extraction_str if 'num_extraction_str' in locals() else raw_value_str_original[:30]}...'")
|
||||
logger.debug(f"ValueError '{e}' bei Konvertierung (get_numeric_filter_value) von '{num_extraction_str if 'num_extraction_str' in locals() and isinstance(num_extraction_str, str) else raw_value_str_original[:30]}...'")
|
||||
return 0.0 if is_umsatz else 0
|
||||
except Exception as e_general:
|
||||
logger.error(f"Unerwarteter Fehler in get_numeric_filter_value für '{raw_value_str_original[:50]}...': {e_general}")
|
||||
@@ -7917,25 +7932,36 @@ class DataProcessor:
|
||||
|
||||
|
||||
# Innerhalb der DataProcessor Klasse
|
||||
# Innerhalb der DataProcessor Klasse (ersetzen Sie Ihre bestehende Version vollständig hiermit)
|
||||
def _get_numeric_value_for_plausi(self, value_str, is_umsatz=False):
|
||||
logger = logging.getLogger(__name__ + "._get_numeric_value_for_plausi")
|
||||
if value_str is None or pd.isna(value_str): return np.nan
|
||||
raw_value_str_clean = str(value_str).strip()
|
||||
|
||||
# Explizit "0" und andere "unbekannt" Strings als NaN behandeln
|
||||
if raw_value_str_clean.lower() in ['', 'k.a.', 'n/a', '-', '0', '0.0', '0,00', '0.000', '0.00']:
|
||||
logger.debug(f"Input '{raw_value_str_clean}' als 'unbekannt' (NaN) interpretiert.")
|
||||
return np.nan
|
||||
|
||||
# Schritt 1: Grundlegende Textbereinigung
|
||||
temp_val = clean_text(raw_value_str_clean)
|
||||
if temp_val.lower() in ['k.a.', 'n/a', '-']: return np.nan
|
||||
if temp_val.lower() in ['k.a.', 'n/a', '-']: return np.nan # Erneute Prüfung nach clean_text
|
||||
|
||||
# Schritt 2: Präfixe, Suffixe, Währungssymbole und Spannen entfernen
|
||||
temp_val = re.sub(r'(?i)^\s*(ca\.?|circa|rund|etwa|ueber|unter|mehr als|weniger als|bis zu)\s+', '', temp_val)
|
||||
temp_val = re.sub(r'[€$£¥]', '', temp_val).strip()
|
||||
temp_val = re.split(r'\s*(-|–|bis)\s*', temp_val, 1)[0].strip()
|
||||
|
||||
num_extraction_str = temp_val.replace("'", "").replace(" ", "")
|
||||
# Schritt 3: Klammerinhalte entfernen
|
||||
num_extraction_str = re.sub(r'\(.*?\)', '', temp_val).strip()
|
||||
|
||||
# Schritt 4: Apostrophe und Leerzeichen zwischen Ziffern entfernen
|
||||
num_extraction_str = num_extraction_str.replace("'", "")
|
||||
num_extraction_str = re.sub(r'(?<=\d)\s+(?=\d)', '', num_extraction_str)
|
||||
|
||||
if not num_extraction_str: return np.nan
|
||||
|
||||
# Schritt 5: Punkte und Kommas als Tausender-/Dezimaltrennzeichen standardisieren
|
||||
has_dot = '.' in num_extraction_str
|
||||
has_comma = ',' in num_extraction_str
|
||||
|
||||
@@ -7944,10 +7970,10 @@ class DataProcessor:
|
||||
num_extraction_str = num_extraction_str.replace(',', '')
|
||||
else:
|
||||
num_extraction_str = num_extraction_str.replace('.', '').replace(',', '.')
|
||||
elif has_comma:
|
||||
elif has_comma:
|
||||
if num_extraction_str.count(',') == 1 and re.search(r',\d{1,2}$', num_extraction_str) and not re.search(r',\d{3}', num_extraction_str):
|
||||
num_extraction_str = num_extraction_str.replace(',', '.')
|
||||
else:
|
||||
else:
|
||||
num_extraction_str = num_extraction_str.replace(',', '')
|
||||
elif has_dot:
|
||||
if num_extraction_str.count('.') == 1 and re.search(r'\.\d{1,2}$', num_extraction_str) and not re.search(r'\.\d{3}', num_extraction_str):
|
||||
@@ -7955,27 +7981,32 @@ class DataProcessor:
|
||||
else:
|
||||
num_extraction_str = num_extraction_str.replace('.', '')
|
||||
|
||||
# Schritt 6: Finale Validierung und Konvertierung zu float
|
||||
if not re.fullmatch(r'-?\d+(\.\d+)?', num_extraction_str):
|
||||
logger.debug(f"Kein gültiger numerischer String nach Trennzeichenbehandlung: '{num_extraction_str}' (Original: '{raw_value_str_clean}')")
|
||||
return np.nan
|
||||
|
||||
try:
|
||||
num_val = float(num_extraction_str)
|
||||
num_val = float(num_extraction_str) # Der reine Zahlenwert aus dem String
|
||||
|
||||
# Schritt 7: Einheiten-Skalierung zum absoluten Wert
|
||||
original_lower = raw_value_str_clean.lower()
|
||||
final_num_absolute = num_val
|
||||
|
||||
if is_umsatz:
|
||||
if is_umsatz: # Ziel ist der absolute Euro-Betrag
|
||||
if re.search(r'\bmrd\s*\b|\bmilliarden\s*\b|\bbillion\s*\b', original_lower):
|
||||
final_num_absolute = num_val * 1000000000.0
|
||||
elif re.search(r'\btsd\s*\b|\btausend\s*\b', original_lower):
|
||||
final_num_absolute = num_val * 1000.0
|
||||
else:
|
||||
else: # Annahme: num_val ist bereits in Mio (z.B. "173" aus CRM), konvertiere zu absolutem Euro
|
||||
final_num_absolute = num_val * 1000000.0
|
||||
else:
|
||||
else: # Mitarbeiter (absolute Zahl, außer bei expliziten Einheiten)
|
||||
if re.search(r'\bmrd\s*\b|\bmilliarden\s*\b|\bbillion\s*\b', original_lower): final_num_absolute = num_val * 1000000000.0
|
||||
elif re.search(r'\bmio\s*\b|\bmillionen\s*\b|\bmill[.]?\s*\b', original_lower): final_num_absolute = num_val * 1000000.0
|
||||
elif re.search(r'\btsd\s*\b|\btausend\s*\b', original_lower): final_num_absolute = num_val * 1000.0
|
||||
|
||||
# Explizite "0"-Strings wurden oben bereits zu NaN.
|
||||
# Wenn final_num_absolute hier 0.0 ist, dann kam es von einer Berechnung (z.B. "0 Tsd" oder "0 Mio").
|
||||
return final_num_absolute
|
||||
|
||||
except ValueError as e:
|
||||
|
||||
Reference in New Issue
Block a user