# Data format `mobts` expects mobility count data as a single pandas DataFrame containing all counters together, and not one DataFrame per counter. Each row represents one observation: one c0ounter, at one timestamp, with one count. `mobts` supports both **hourly** and **daily** granularity, but a given dataset should be consistently one or the other. ## Typical input data A typical dataset may look like this: | counter_id | date | N_veh | |------------|------------|-------| | A | 2025-01-01 | 120 | | A | 2025-01-02 | 135 | | A | 2025-01-03 | NaN | | B | 2025-01-01 | 90 | | B | 2025-01-02 | 95 | Your column names do not need to match this example. You will tell `mobts` which column is which via the `counter_col`, `timestamp_col`, and `count_col` arguments (see [Quickstart](quickstart.md)). You also do not need to pre-populate every expected timestamp as its own row. `mobts` accepts sparse input and handles gaps in the time index internally. Provide whatever observations you actually have. An explicit `NaN` row for a missing period is accepted, but not obligated. ## What mobts does with your columns Internally, `mobts` renames your three input columns to a fixed set of canonical names (`counter`, `timestamp`, `count`), and derives several temporal columns automatically. `date`, `weekday`, and `week_num` for daily data, plus `hour` and hour-of-week (`how`) for hourly data. You do not need to provide these yourself. The canonical names, and every other default used across the package, can be overridden. See [Configuration](configuration.md). ## Optional metadata columns If your dataset has extra columns you want preserved through preprocessing and imputation (for example a station name or spatial identifier) without them being treated as count data, pass their names via `metadata_cols` when calling `run()`. ## Assumptions and checks Before using the package, make sure that: - the timestamp column can be parsed as a pandas datetime - the count column is numeric - missing values are represented as `NaN`, and not `0` Before running preprocessing or imputation, it is usually a good idea to check: ```python df.head() df.info() df.isna().sum() ``` This helps confirm the dataset has the expected columns and types before it reaches the pipeline.