""" Standarisasi Kolom Module Memetakan kolom dari berbagai tahun ke kolom standar """ import pandas as pd import json from pathlib import Path from typing import Dict, List, Optional class ColumnStandardizer: """ Kelas untuk menstandarisasi kolom dari berbagai file Excel dengan struktur kolom yang berbeda-beda """ def __init__(self, mapping_file: str = None): """ Args: mapping_file: Path ke file JSON mapping kolom """ if mapping_file is None: # Default path mapping_file = Path(__file__).parent.parent / "column_mapping.json" self.mapping_file = Path(mapping_file) self.mappings = self._load_mappings() def _load_mappings(self) -> Dict: """Load mapping dari file JSON""" if not self.mapping_file.exists(): raise FileNotFoundError(f"Mapping file tidak ditemukan: {self.mapping_file}") with open(self.mapping_file, 'r', encoding='utf-8') as f: return json.load(f) def get_mapping(self, year: str) -> Dict: """ Ambil mapping untuk tahun tertentu Args: year: Tahun data (2022, 2023, 2024) Returns: Dictionary dengan mapping kolom """ if year not in self.mappings: raise ValueError(f"Mapping untuk tahun {year} tidak ditemukan. " f"Tahun yang tersedia: {list(self.mappings.keys())}") return self.mappings[year] def detect_year(self, df: pd.DataFrame, filename: str = None) -> Optional[str]: """ Deteksi tahun dari DataFrame atau filename Args: df: DataFrame untuk dicek kolomnya filename: Nama file (opsional) Returns: Tahun yang terdeteksi atau None """ # Cek dari filename if filename: for year in self.mappings.keys(): if year in filename: return year # Cek dari kolom yang tersedia available_years = [] for year, mapping in self.mappings.items(): match_count = sum(1 for col in mapping.values() if col in df.columns) if match_count >= 2: # Minimal 2 kolom cocok available_years.append((year, match_count)) if available_years: # Pilih tahun dengan match terbanyak return max(available_years, key=lambda x: x[1])[0] return None def standardize(self, df: pd.DataFrame, year: str = None, filename: str = None) -> pd.DataFrame: """ Standarisasi kolom DataFrame Args: df: DataFrame asli year: Tahun data (auto-detect jika None) filename: Nama file (opsional, untuk auto-detect) Returns: DataFrame dengan kolom standar """ # Deteksi tahun jika tidak specified if year is None: year = self.detect_year(df, filename) if year is None: raise ValueError("Tidak dapat mendeteksi tahun data. " f"Pastikan kolom sesuai dengan mapping yang tersedia.") # Ambil mapping mapping = self.get_mapping(year) # Buat DataFrame baru dengan kolom standar result = pd.DataFrame() for target_col, source_col in mapping.items(): if source_col in df.columns: result[target_col] = df[source_col] else: result[target_col] = None return result def standardize_multiple(self, dfs: List[pd.DataFrame], years: List[str] = None, filenames: List[str] = None) -> List[pd.DataFrame]: """ Standarisasi multiple DataFrame sekaligus Args: dfs: List DataFrame years: List tahun (auto-detect jika None) filenames: List nama file (opsional) Returns: List DataFrame yang sudah distandarisasi """ results = [] for i, df in enumerate(dfs): year = years[i] if years else None filename = filenames[i] if filenames else None standardized = self.standardize(df, year, filename) results.append(standardized) return results def merge_datasets(dfs: List[pd.DataFrame]) -> pd.DataFrame: """ Gabungkan multiple DataFrame menjadi satu Args: dfs: List DataFrame Returns: DataFrame gabungan """ return pd.concat(dfs, ignore_index=True) def clean_data(df: pd.DataFrame) -> pd.DataFrame: """ Basic data cleaning Args: df: DataFrame Returns: DataFrame yang sudah dibersihkan """ result = df.copy() # Hapus baris dengan semua nilai kosong result = result.dropna(how='all') # Hapus duplikat result = result.drop_duplicates() # Isi nilai kosong dengan string kosong result = result.fillna('') return result if __name__ == "__main__": # Contoh penggunaan standardizer = ColumnStandardizer() # Sample data 2024 sample_2024 = pd.DataFrame({ "4. Nama Lengkap / nmmhsmsmh (Gunakan Huruf Besar)": ["Ali", "Budi"], "9. Apa nama perusahaan/kantor tempat Anda bekerja? f5b": ["Google", "Tokopedia"], "10. Bila Anda berwiraswasta, apa posisi/jabatan Anda saat ini ? f5c": ["Engineer", "Analyst"] }) # Standarisasi standardized = standardizer.standardize(sample_2024, year="2024") print("Data Standarisasi:") print(standardized)