# walkingpandas Tutorial Examples

Self-contained tutorial scripts that demonstrate all library functionality. Each example uses small generated data (no external files) and can be run from the project root.

## How to run

From the project root:

```bash
uv run python examples/01_getting_started.py
```

Or with a regular Python environment where `walkingpandas` is installed:

```bash
python examples/01_getting_started.py
```

## Script index

| Script | Description | Main concepts |
|--------|-------------|---------------|
| [01_getting_started.py](01_getting_started.py) | Minimal Network + WalkFrame + compute() | Lazy evaluation, building a chain, `.compute()`, `nodes=`/`edges=`, `.network` |
| [02_network_creation.py](02_network_creation.py) | Build networks from different sources | Parquet, GeoDataFrames, DataFrame x/y, `from_gdfs`, `from_networkx`, `from_walks` |
| [03_walkframe_basics.py](03_walkframe_basics.py) | Filter, limit, export | `.filter()`, `.limit()`, `.to_pandas()`, `.to_geopandas()` |
| [04_graph_validation.py](04_graph_validation.py) | Simple paths, cycles, complex walks | `only_simple_paths()`, `only_cycles()`, `only_complex_walks()` |
| [05_spatial_filtering.py](05_spatial_filtering.py) | Spatial filters on walks | `passing_through`, `within_bounds`, `intersecting`, `near_point` |
| [06_temporal_queries.py](06_temporal_queries.py) | Time-based filtering and traffic | `filter(time_range=...)`, `edge_traffic_at(time)` |
| [07_aggregations.py](07_aggregations.py) | Counts and lengths | `edge_frequencies()`, `node_frequencies()`, `walk_lengths()` |
| [08_ingestion_io.py](08_ingestion_io.py) | Schema validation and writing | `validate_schema`, `convert_to_superset_format`, `write_walks`, `read_dataset` |
| [09_persistence.py](09_persistence.py) | Save/load Network, connect(), single-file DuckDB | `Network.save/load`, `database=`, `connect()`, `write_duckdb`, `WalkFrame.from_duckdb()` |
| [10_data_quality.py](10_data_quality.py) | Orphan detection | `get_orphaned_records()` |
| [11_full_workflow.py](11_full_workflow.py) | End-to-end pipeline | Create data → write Parquet → load → chain queries → save .duckdb, `from_walks(infer_network=True)` |

### Alternative ways to create Network and WalkFrame

- **Network.from_walks(walks)** — Infer nodes (and optionally edges) from walk Parquet or DataFrame; useful when you only have trajectory data (observed topology). Result has no geometry until you add it.
- **WalkFrame(path, nodes=..., edges=...)** — Pass nodes and edges directly; a Network is built internally. Use when you have GeoDataFrames/DataFrames but don't need a standalone Network first.
- **WalkFrame.from_walks(path, infer_network=True)** — One call: infer network from the same walk data and build the WalkFrame.
- **walks.network** — Access the underlying Network (e.g. to save it, pass to another WalkFrame, or inspect nodes/edges).

## Data schema reference (superset format)

Walk data in Parquet is stored **row-per-step**. Expected columns:

| Column | Required | Description |
|--------|----------|-------------|
| `walk_id` | Yes | Identifier for the trajectory/path |
| `sequence_idx` | Yes | Step order (0, 1, 2, …) |
| `node_id` | Yes | Node at this step |
| `exit_edge` | No | Edge used to leave this node (optional) |
| `timestamp` | No | When the step occurred |
| `dwell_time` | No | Time spent at this node before moving |
| `dynamic_attributes` | No | Extra attributes (e.g. JSON or struct) |

Nodes need `node_id` and optionally geometry (or `x`/`y`); topology-only nodes (e.g. from `Network.from_walks`) have no geometry. Edges need `edge_id`, `source_node`, and `target_node`, plus optional geometry.
