Ursa¶
Polars-shaped dataframes for graph data.
Ursa is a graph analytics library for Python. You write a query the way you write a Polars query. A Rust engine runs it: Apache Arrow for the data, DataFusion for the plan, and parallel, deterministic kernels for the algorithms.
There is no Graph object. An edge table is the graph. Every operation returns a table.
Install¶
The package is ursa-graph. The import name is ursa. Wheels include the compiled core, so you need no Rust toolchain. Python 3.10 or later. See Install for the optional extras.
First example¶
Paste this into a Python session. It needs no files and no network.
import ursa as ur
edges = ur.datasets.load_karate() # 34 nodes, 78 edges, bundled with the package
top = (
edges.nodes()
.with_columns(
degree=ur.degree(edges, direction="both"),
triangles=ur.triangle_count(edges),
community=ur.louvain(edges, seed=1),
)
.sort("degree", descending=True)
.head(5)
.collect()
)
print(top)
shape: (5, 4)
┌───────┬────────┬───────────┬───────────┐
│ id ┆ degree ┆ triangles ┆ community │
│ --- ┆ --- ┆ --- ┆ --- │
│ int64 ┆ uint32 ┆ uint32 ┆ uint32 │
╞═══════╪════════╪═══════════╪═══════════╡
│ 33 ┆ 17 ┆ 15 ┆ 2 │
│ 0 ┆ 16 ┆ 18 ┆ 0 │
│ 32 ┆ 12 ┆ 13 ┆ 2 │
│ 2 ┆ 10 ┆ 11 ┆ 0 │
│ 1 ┆ 9 ┆ 12 ┆ 0 │
└───────┴────────┴───────────┴───────────┘
What happened:
edges.nodes()starts a lazy table of the node ids.with_columns(...)adds three columns. Each is a graph algorithm overedges.sort(...)andhead(5)shape the rows.collect()runs all of it as one query and returns Arrow data.
To run the same query over your own data, change the first line:
Nothing after that line changes.
What you get¶
-
A dataframe API
with_columns,filter,sort,group_by,join. If you know Polars, you know the shape. Lazy untilcollect(). -
The standard algorithms
Degree, PageRank, components, triangles, clustering, closeness, betweenness, Louvain, label propagation. Each with a weighted form. Hops, shortest paths, random walks.
-
Your data, where it is
Parquet and CSV, local or on S3, GCS, and Azure. Polars, pandas, pyarrow, NetworkX, NumPy, and SciPy in memory. Arrow in, Arrow out, no copies.
-
Results you can check
Every kernel is deterministic on any thread count. Each one is pinned to the NetworkX call it matches, and the test suite checks it.
Next steps¶
- Quickstart: a ten-minute session that uses most of the API.
- Guides: one task per page, with code that runs.
- Reference: every public name.
Ursa is version 0.3 and in active development. The Limits page lists what does not run yet.