NPAP is an open-source Python library for partitioning and aggregating network graphs, with a special focus on electrical power systems. Built on top of NetworkX, it provides a clean strategy-based architecture that makes it easy to cluster networks and reduce their complexity while preserving essential properties.
Whether you're working with power grids, transportation networks, or any graph-based spatial data, NPAP helps you simplify complex networks into manageable pieces.
Note
Project contributors from IEE (Institute of Electricity Economics and Energy Innovation) at the Technical University of Graz are supported by the Research Center Energetic and funded by the European Union (ERC, NetZero-Opt, 101116212).
For comprehensive guides, API reference, and tutorials, visit the official documentation:
- Multiple Partitioning Algorithms - K-means, K-medoids, DBSCAN, HDBSCAN, and hierarchical clustering
- Distance Metrics - Euclidean for local coordinates, Haversine for geographic data
- Electrical Distance - Partition based on PTDF-derived electrical proximity
- Voltage-Aware Clustering - Respects voltage levels and transformer boundaries
- Flexible Aggregation - Sum, average, or custom strategies for node/edge properties
- Extensible Design - Easy to add your own partitioning or aggregation strategies
pip install npapThis example runs as-is: NPAP downloads and caches the network for you. It reduces the European high-voltage grid from 6,863 buses to 50, and takes about a minute.
import npap
from npap import AggregationProfile
from npap.datasets import fetch_pypsa_eur
files = fetch_pypsa_eur()
manager = npap.PartitionAggregatorManager()
manager.load_data(
strategy="csv_files",
node_file=str(files["buses.csv"]),
edge_file=str(files["lines.csv"]),
)
manager.aggregate_parallel_edges(
edge_properties={"x": "equivalent_reactance", "s_nom": "sum"},
default_strategy="average",
)
manager.partition(strategy="geographical_kmedoids_haversine", n_clusters=50)
profile = AggregationProfile(
topology_strategy="simple",
node_properties={"lat": "average", "lon": "average", "voltage": "first"},
edge_properties={"x": "equivalent_reactance", "s_nom": "sum"},
default_node_strategy="average",
default_edge_strategy="average",
)
reduced = manager.aggregate(profile=profile)
manager.plot_network(graph=reduced, style="simple", title="Reduced network")The result is a 50-bus, 153-line network — 0.7% of the buses you started with.
The Quick Start guide explains each step and how the configuration choices affect the outcome, and the example notebooks run the full voltage-aware pipeline, which respects transformers, DC links and voltage levels.
We warmly welcome contributions from everyone! Whether it's fixing a typo, improving documentation, reporting bugs, or implementing new features — every contribution matters.
Please read our Contributing Guide to get started, or visit the full Contributing Documentation for detailed guidelines.
Found a bug, want to request a feature, or have a question about using NPAP? Open an issue — the template picker will guide you to the right form. Please search the existing issues first, in case it has already been reported.
NPAP is released under the MIT License.
Funded by the European Union (ERC, NetZero-Opt, 101116212). Views and opinions expressed are however those of the author(s) only and do not necessarily reflect those of the European Union or the European Research Council. Neither the European Union nor the granting authority can be held responsible for them.
Built with care for the open-source community 🫰

