Download inspect_data.py from slappatuski/batterySwap: direct link, hf CLI and curl.
- Browser
- Download file 2.8 kB
-
https://huggingface.co/slappatuski/batterySwap/resolve/main/inspect_data.py
- Command line
-
hf download hf://slappatuski/batterySwap/inspect_data.py
-
curl -L -o inspect_data.py https://huggingface.co/slappatuski/batterySwap/resolve/main/inspect_data.py
2.8 kB
| """ | |
| Data-schema inspector. | |
| Prints exactly what raw signals are available so we can decide which FEATURES to | |
| add. The current model (batteryswap_example/train.py, BaseRULModel) only uses | |
| value_cols=('voltage', 'temperature') from the timeseries and ignores device | |
| metadata entirely -- if the parquet or devices.csv carry more predictive signal | |
| (current, soc, resistance, cycle count, install age, ...) we are leaving accuracy | |
| on the table, and late_swap + early_swap (84% of total cost) is now a | |
| prediction-accuracy problem. | |
| Run: | |
| BATTERYSWAP_DATASET_PATH=BatterySwapAI-2026-Public \ | |
| venv/bin/python3 inspect_data.py | |
| """ | |
| import os | |
| from pathlib import Path | |
| import pandas as pd | |
| from batteryswap_example.train import load_dataset | |
| def main(): | |
| dataset_path = os.environ.get("BATTERYSWAP_DATASET_PATH") | |
| assert dataset_path, "set BATTERYSWAP_DATASET_PATH (e.g. BatterySwapAI-2026-Public)" | |
| split_path = Path(dataset_path) / "train" | |
| locations, timeseries, eol_times, scenarios = load_dataset(split_path) | |
| print("=" * 70) | |
| print("TIMESERIES (battery_metrics) -- one row per device per timestamp") | |
| print("=" * 70) | |
| print("index names :", list(timeseries.index.names)) | |
| print("columns :", list(timeseries.columns)) | |
| print("dtypes :\n", timeseries.dtypes) | |
| print("shape :", timeseries.shape) | |
| print("head:\n", timeseries.head(3)) | |
| # Numeric columns beyond voltage/temperature are candidate new features. | |
| numeric = timeseries.select_dtypes("number").columns.tolist() | |
| used = ["voltage", "temperature"] | |
| unused = [c for c in numeric if c not in used] | |
| print("\nnumeric columns NOT currently used as features:", unused) | |
| print("\n" + "=" * 70) | |
| print("LOCATIONS -- per-device placement the planner sees") | |
| print("=" * 70) | |
| print("columns:", list(locations.columns)) | |
| print(locations.head(3)) | |
| print("\n" + "=" * 70) | |
| print("devices.csv -- has install start_time => TRUE device AGE feature") | |
| print("=" * 70) | |
| dev = pd.read_csv(split_path / "devices.csv") | |
| print("columns:", list(dev.columns)) | |
| print(dev.head(3)) | |
| # How old are devices? (age = plan time - install time). Strong RUL signal. | |
| if "start_time" in dev.columns: | |
| st = pd.to_datetime(dev["start_time"], utc=True, errors="coerce") | |
| span = (pd.Timestamp.utcnow() - st).dt.days | |
| print("\ninstall-age (days) distribution:") | |
| print(span.describe()) | |
| print("\n" + "=" * 70) | |
| print("eol_times -- censoring rate") | |
| print("=" * 70) | |
| eol = pd.Series(eol_times) | |
| n = len(eol) | |
| n_obs = eol.notna().sum() | |
| print(f"devices={n} observed_eol={n_obs} censored(blank)={n - n_obs} " | |
| f"({100 * (n - n_obs) / max(n, 1):.1f}% censored)") | |
| if __name__ == "__main__": | |
| main() | |