Spaces:
Paused
Paused
| """ | |
| Implements: 02_Data/06_SYNTHETIC_DATA_GENERATION.md | |
| Implements: 01_Project/04_INTERFACE_CONTRACTS.md | |
| """ | |
| import pandas as pd | |
| from pathlib import Path | |
| import logging | |
| logger = logging.getLogger(__name__) | |
| class FeatureEngineer: | |
| """ | |
| Transforms raw authentication telemetry into engineered ML feature vectors. | |
| """ | |
| def process(self, input_path: str, output_path: str) -> pd.DataFrame: | |
| logger.info(f"Loading raw logs from {input_path}") | |
| df = pd.read_parquet(input_path) | |
| # Temporal Features | |
| df['hour_of_day'] = df['timestamp'].dt.hour | |
| df['day_of_week'] = df['timestamp'].dt.dayofweek | |
| df['is_weekend'] = df['day_of_week'].isin([5, 6]).astype(int) | |
| df['is_working_hour'] = ((df['hour_of_day'] >= 8) & (df['hour_of_day'] <= 18)).astype(int) | |
| # Behavior Features | |
| df['is_failure'] = (df['authentication_result'] == 'Failure').astype(int) | |
| # Geographic Features | |
| df['country_encoded'] = df['country'].astype('category').cat.codes | |
| # Device Features | |
| df['is_mfa'] = (df['authentication_method'] == 'MFA').astype(int) | |
| # Velocity / Historical Features | |
| df = df.sort_values(['user_id', 'timestamp']) | |
| df['time_since_last_login'] = df.groupby('user_id')['timestamp'].diff().dt.total_seconds().fillna(0) | |
| df['rolling_failures_24h'] = df.groupby('user_id')['is_failure'].transform( | |
| lambda x: x.rolling(10, min_periods=1).sum() | |
| ) | |
| # Sort back to original chronological event ID order | |
| df = df.sort_values('event_id').reset_index(drop=True) | |
| out_path = Path(output_path) | |
| out_path.parent.mkdir(parents=True, exist_ok=True) | |
| df.to_parquet(out_path, index=False) | |
| logger.info(f"Persisted feature vectors to {output_path}") | |
| return df | |