TIF_E41253310/Backend/app/parsers/column_finder.py

84 lines
2.5 KiB
Python

import re
import pandas as pd
def normalize(col_name):
"""Normalize nama kolom - lowercase, collapse spaces, and strip whitespace"""
if pd.isna(col_name):
return ""
# Collapse multiple whitespace characters into single space
cleaned = re.sub(r'\s+', ' ', str(col_name))
return cleaned.strip().lower()
def find_column(source_cols, possible_names):
"""
Cari kolom dari beberapa kemungkinan nama.
Args:
source_cols: list kolom dari DataFrame
possible_names: list kemungkinan nama kolom
Returns:
Nama kolom yang ditemukan, atau None
"""
source_cols_map = {normalize(c): c for c in source_cols}
# Step 1: Direct normalized match
for name in possible_names:
norm_name = normalize(name)
if norm_name in source_cols_map:
return source_cols_map[norm_name]
# Step 2: Code token match (e.g. 'f1761', 'f5a1', 'f1101', 'f502', etc.)
for name in possible_names:
norm_name = normalize(name)
# Extract question code if present (e.g., 'f1761', 'f5a1', 'f8', etc.)
match = re.search(r'\b(f\d+[a-z]?\d*)\b', norm_name)
if match:
code = match.group(1)
for orig_norm, orig_col in source_cols_map.items():
if re.search(r'\b' + re.escape(code) + r'\b', orig_norm):
return orig_col
return None
def get_value(row, source_cols, possible_names, default=None):
"""
Ambil nilai dari row dengan cari kolom dulu.
Args:
row: pandas Series (satu row)
source_cols: list kolom dari DataFrame
possible_names: list kemungkinan nama kolom
default: nilai default jika tidak ditemukan
Returns:
Nilai dari row, atau default
"""
col = find_column(source_cols, possible_names)
if col and pd.notna(row.get(col)):
val = row[col]
# Convert int/float
if isinstance(val, (int, float)):
return int(val) if val == int(val) else val
return str(val).strip()
return default
def check_available_columns(df_cols: list) -> dict:
"""
Check kolom apa saja yang tersedia di dataframe.
Berguna untuk debugging.
"""
result = {
'total': len(df_cols),
'has_email': any('email' in str(c).lower() for c in df_cols),
'has_nim': any('nim' in str(c).lower() for c in df_cols),
'has_f1102': 'F1102' in df_cols,
'has_f5b': 'F5b' in df_cols,
'has_f1762': 'F1762' in df_cols,
}
return result