Download app/services/preprocessing.py from alaa3/TouRa: direct link, hf CLI and curl.
- Browser
- Download file 2.87 kB
-
https://huggingface.co/spaces/alaa3/TouRa/resolve/main/app/services/preprocessing.py
- Command line
-
hf download hf://spaces/alaa3/TouRa/app/services/preprocessing.py
-
curl -L -o preprocessing.py https://huggingface.co/spaces/alaa3/TouRa/resolve/main/app/services/preprocessing.py
2.87 kB
| """ | |
| Data preprocessing pipeline. | |
| Handles loading, cleaning, and city extraction from the places CSV dataset. | |
| """ | |
| import logging | |
| import json | |
| from pathlib import Path | |
| from typing import Optional | |
| import pandas as pd | |
| from app.core.constants import EGYPT_CITIES | |
| logger = logging.getLogger(__name__) | |
| def extract_city(address: Optional[str]) -> Optional[str]: | |
| """ | |
| Extract an Egyptian city name from a raw address string. | |
| Args: | |
| address: Raw address text, may be None / NaN. | |
| Returns: | |
| Matched city name or None. | |
| """ | |
| if pd.isna(address) or not address: | |
| return None | |
| for city in EGYPT_CITIES: | |
| if city.lower() in address.lower(): | |
| return city | |
| return None | |
| def load_and_preprocess(csv_path: str) -> pd.DataFrame: | |
| """ | |
| Load the places CSV and add a 'city' column derived from addresses. | |
| Args: | |
| csv_path: Path to the raw CSV file. | |
| Returns: | |
| Preprocessed DataFrame with a 'city' column. | |
| """ | |
| logger.info("Loading dataset from %s", csv_path) | |
| data = pd.read_csv(csv_path) | |
| logger.info("Loaded %d rows, columns: %s", len(data), list(data.columns)) | |
| data["city"] = data["address"].apply(extract_city) | |
| logger.info("City extraction complete. Distribution:\n%s", data["city"].value_counts()) | |
| return data | |
| def filter_by_city(data: pd.DataFrame, city: str) -> pd.DataFrame: | |
| """ | |
| Filter the DataFrame to rows belonging to a specific city. | |
| Args: | |
| data: Preprocessed DataFrame. | |
| city: City name to filter on (case-insensitive match against 'city' column). | |
| Returns: | |
| Filtered DataFrame. | |
| """ | |
| filtered = data[data["city"].str.lower() == city.lower()] | |
| logger.info("Filtered to %d rows for city '%s'", len(filtered), city) | |
| return filtered | |
| def dataframe_to_json_string(df: pd.DataFrame) -> str: | |
| """ | |
| Serialize a DataFrame to a compact JSON string (records orientation). | |
| Args: | |
| df: DataFrame to serialize. | |
| Returns: | |
| JSON string. | |
| """ | |
| return df.to_json(orient="records", force_ascii=False) | |
| def save_city_json(df: pd.DataFrame, output_path: str) -> None: | |
| """ | |
| Persist a city-filtered DataFrame as a JSON file. | |
| Args: | |
| df: DataFrame for one city. | |
| output_path: Destination file path. | |
| """ | |
| path = Path(output_path) | |
| path.parent.mkdir(parents=True, exist_ok=True) | |
| json_str = dataframe_to_json_string(df) | |
| with open(path, "w", encoding="utf-8") as f: | |
| f.write(json_str) | |
| logger.info("Saved city JSON to %s", path) | |
| def load_city_json(json_path: str) -> pd.DataFrame: | |
| """ | |
| Load a previously saved city JSON back into a DataFrame. | |
| Args: | |
| json_path: Path to the JSON file. | |
| Returns: | |
| DataFrame. | |
| """ | |
| logger.info("Loading city JSON from %s", json_path) | |
| return pd.read_json(json_path) | |