File size: 2,795 Bytes
11ab05d
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
"""
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()