Skip to main content

PolarsGrouper

PolarsGrouper is a Rust-based extension for Polars that provides efficient graph analysis capabilities, with a focus on component grouping and network analysis.

Core Features

Component Grouping

  • super_merger: Easy-to-use wrapper for grouping connected components
  • super_merger_weighted: Component grouping with weight thresholds
  • Efficient implementation using Rust and Polars
  • Works with both eager and lazy Polars DataFrames

Hierarchy / BOM Explosion

  • hierarchy_totals, hierarchy_levels, hierarchy_paths: explode a parent → child edge list (bill of materials, chart of accounts, WBS) into its transitive closure, with quantities rolled up along every path
  • Replaces WITH RECURSIVE / CONNECT BY queries and for-loops, and runs inside lazy queries

Additional Graph Analytics

  • Shortest Path Analysis: Find shortest paths between nodes
  • PageRank: Calculate node importance scores
  • Betweenness Centrality: Identify key bridge nodes
  • Association Rules: Discover item relationships and patterns

Installation

pip install polars-grouper

# For development:
python -m venv .venv
source .venv/bin/activate
maturin develop

Usage Examples

Basic Component Grouping

The core functionality uses super_merger to identify connected components:

import polars as pl
from polars_grouper import super_merger

df = pl.DataFrame({
    "from": ["A", "B", "C", "D", "E", "F"],
    "to": ["B", "C", "A", "E", "F", "D"],
    "value": [1, 2, 3, 4, 5, 6]
})

result = super_merger(df, "from", "to")
print(result)

Weighted Component Grouping

For cases where edge weights matter:

from polars_grouper import super_merger_weighted

df = pl.DataFrame({
    "from": ["A", "B", "C", "D", "E"],
    "to": ["B", "C", "D", "E", "A"],
    "weight": [0.9, 0.2, 0.05, 0.8, 0.3]
})

result = super_merger_weighted(
    df, 
    "from", 
    "to", 
    "weight",
    weight_threshold=0.3
)
print(result)

Hierarchy / BOM Explosion

Resolve a bill of materials in one lazy expression. Quantities multiply along a path (4 wheels × 5 screws) and add up across paths (+ 20 screws directly on the car):

import polars as pl
from polars_grouper import hierarchy_totals, hierarchy_levels, hierarchy_paths

bom = pl.LazyFrame({
    "parent": ["car", "car", "car", "wheel", "wheel", "wheel", "rim"],
    "child": ["wheel", "steering_wheel", "screw", "tyre", "rim", "screw", "iron"],
    "qty": [4.0, 1.0, 20.0, 1.0, 1.0, 5.0, 2.5],
})

totals = bom.select(hierarchy_totals("parent", "child", "qty").alias("bom")).unnest("bom")

# Raw materials needed for one car
totals.filter(pl.col("ancestor") == "car", pl.col("is_leaf")).collect()
# ┌──────────┬────────────────┬───────┬──────────┬─────────┐
# │ ancestor ┆ descendant     ┆ level ┆ quantity ┆ is_leaf │
# ╞══════════╪════════════════╪═══════╪══════════╪═════════╡
# │ car      ┆ steering_wheel ┆ 1     ┆ 1.0      ┆ true    │
# │ car      ┆ screw          ┆ 1     ┆ 40.0     ┆ true    │
# │ car      ┆ tyre           ┆ 2     ┆ 4.0      ┆ true    │
# │ car      ┆ iron           ┆ 3     ┆ 10.0     ┆ true    │
# └──────────┴────────────────┴───────┴──────────┴─────────┘

Three functions, one per level of detail. They share column names, so each is an aggregation of the next:

function one row per extra columns
hierarchy_totals ancestor, descendant level is the shallowest level
hierarchy_levels ancestor, descendant, level
hierarchy_paths path (an indented BOM) parent, quantity_per, path

All three take top_level_only (explode finished products only), include_self (add a level-0 row per node) and max_depth. A cycle in the data raises an error that names it.

The same works for any hierarchy. To roll up general-ledger balances along a chart of accounts, link every account to itself and to everything below it, then aggregate:

closure = accounts.select(
    hierarchy_totals("parent_account", "account", include_self=True).alias("closure")
).unnest("closure")

balances = (
    closure.join(transactions, left_on="descendant", right_on="account")
    .group_by("ancestor")
    .agg(pl.col("amount").sum())
)

Additional Graph Analytics

Shortest Path Analysis

Find shortest paths between nodes:

from polars_grouper import calculate_shortest_path

df = pl.DataFrame({
    "from": ["A", "A", "B", "C"],
    "to": ["B", "C", "C", "D"],
    "weight": [1.0, 2.0, 1.0, 1.5]
})

paths = df.select(
    calculate_shortest_path(
        pl.col("from"),
        pl.col("to"),
        pl.col("weight"),
        directed=False
    ).alias("paths")
).unnest("paths")

PageRank Calculation

Calculate node importance:

from polars_grouper import page_rank

df = pl.DataFrame({
    "from": ["A", "A", "B", "C", "D"],
    "to": ["B", "C", "C", "A", "B"]
})

rankings = df.select(
    page_rank(
        pl.col("from"),
        pl.col("to"),
        damping_factor=0.85
    ).alias("pagerank")
).unnest("pagerank")

Association Rule Mining

Discover item relationships:

from polars_grouper import graph_association_rules

transactions = pl.DataFrame({
    "transaction_id": [1, 1, 1, 2, 2, 3],
    "item_id": ["A", "B", "C", "B", "D", "A"],
    "frequency": [1, 2, 1, 1, 1, 1]
})

rules = transactions.select(
    graph_association_rules(
        pl.col("transaction_id"),
        pl.col("item_id"),
        pl.col("frequency"),
        min_support=0.1
    ).alias("rules")
).unnest("rules")

Betweenness Centrality

Identify bridge nodes:

from polars_grouper import betweenness_centrality

df = pl.DataFrame({
    "from": ["A", "A", "B", "C", "D", "E"],
    "to": ["B", "C", "C", "D", "E", "A"]
})

centrality = df.select(
    betweenness_centrality(
        pl.col("from"),
        pl.col("to"),
        normalized=True
    ).alias("centrality")
).unnest("centrality")

Performance

The library is implemented in Rust for high performance:

  • Efficient memory usage
  • Fast computation for large graphs
  • Seamless integration with Polars' lazy evaluation

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

License

This project is licensed under the MIT License - see the LICENSE file for details.

Metadata

Release files for polars-grouper 0.7.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for polars-grouper 0.7.0
File Size Uploaded Provenance Actions
polars_grouper-0.7.0.tar.gz 57.1 kB Without provenance Details for polars_grouper-0.7.0.tar.gz

Built distributions (wheels)

Table of built distributions (wheels) for polars-grouper 0.7.0
File Actions
polars_grouper-0.7.0-cp310-abi3-win_amd64.whl CPython 3.10 abi3 Windows x86-64 Details for polars_grouper-0.7.0-cp310-abi3-win_amd64.whl
polars_grouper-0.7.0-cp310-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl CPython 3.10 abi3 Linux glibc 2.17+ x86-64 Details for polars_grouper-0.7.0-cp310-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl
polars_grouper-0.7.0-cp310-abi3-manylinux2014_i686.manylinux_2_17_i686.whl CPython 3.10 abi3 Linux glibc 2.17+ x86-32 Details for polars_grouper-0.7.0-cp310-abi3-manylinux2014_i686.manylinux_2_17_i686.whl
polars_grouper-0.7.0-cp310-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl CPython 3.10 abi3 Linux glibc 2.17+ ARM64 Details for polars_grouper-0.7.0-cp310-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl
polars_grouper-0.7.0-cp310-abi3-macosx_11_0_arm64.whl CPython 3.10 abi3 macOS 11.0+ ARM64 Details for polars_grouper-0.7.0-cp310-abi3-macosx_11_0_arm64.whl
polars_grouper-0.7.0-cp310-abi3-macosx_10_12_x86_64.whl CPython 3.10 abi3 macOS 10.12+ x86-64 Details for polars_grouper-0.7.0-cp310-abi3-macosx_10_12_x86_64.whl

Total release size: 30.7 MB

Release files / polars_grouper-0.7.0.tar.gz

Download URL polars_grouper-0.7.0.tar.gz
Size 57.1 kB
Tags Source
SHA-256 checksum
How to use checksums
cc8232098ae88d271f6ca492676769f181390d1dc7eac828710c7481edd5e7ee
BLAKE2b-256 checksum
How to use checksums
f5e4d3eb7223b9c414693caf3862f549f66f6018803abc4c7b291362e8b1d939
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via maturin/1.16.0

Release files / polars_grouper-0.7.0-cp310-abi3-win_amd64.whl

Download URL polars_grouper-0.7.0-cp310-abi3-win_amd64.whl
Size 4.7 MB
Tags CPython 3.10 Windows x86-64 abi3
SHA-256 checksum
How to use checksums
5445038d95b93d800c7fb688cf9c9d2c51c331b368a0706712dde68b8fd41dad
BLAKE2b-256 checksum
How to use checksums
454efcfface86009dfaba048e9a5c316317c5c4910659cb62e9c56a52fbc9ac5
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via maturin/1.16.0

Release files / polars_grouper-0.7.0-cp310-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl

Download URL polars_grouper-0.7.0-cp310-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl
Size 5.4 MB
Tags CPython 3.10 Linux glibc 2.17+ x86-64 abi3
SHA-256 checksum
How to use checksums
a2ba08827d275e4031d02c178de811c7a84707de9bfb436a0e8d61055ca643a6
BLAKE2b-256 checksum
How to use checksums
887046edf057c7d2915ad12a2e787ddeabc11a205bf6a3fea5be7daffd8036a1
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via maturin/1.16.0

Release files / polars_grouper-0.7.0-cp310-abi3-manylinux2014_i686.manylinux_2_17_i686.whl

Download URL polars_grouper-0.7.0-cp310-abi3-manylinux2014_i686.manylinux_2_17_i686.whl
Size 6.1 MB
Tags CPython 3.10 Linux glibc 2.17+ x86-32 abi3
SHA-256 checksum
How to use checksums
164a7c74275bf302a14089239abe3578d5f84dd5a0c48d8bb97445f8565b2416
BLAKE2b-256 checksum
How to use checksums
2f489ba6780dac64d9cf41c8366004b2c46f7e0134cb6ecf7ee221d6477d7b63
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via maturin/1.16.0

Release files / polars_grouper-0.7.0-cp310-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl

Download URL polars_grouper-0.7.0-cp310-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl
Size 5.3 MB
Tags CPython 3.10 Linux glibc 2.17+ ARM64 abi3
SHA-256 checksum
How to use checksums
9fccff986798dbf08ff261093f1a54a815e982945a84ffcd43596f7608cc39a0
BLAKE2b-256 checksum
How to use checksums
6f3eb93136e14ee2ec5bd556974277efd8dbae9d1e559ec003769bd66486eb9c
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via maturin/1.16.0

Release files / polars_grouper-0.7.0-cp310-abi3-macosx_11_0_arm64.whl

Download URL polars_grouper-0.7.0-cp310-abi3-macosx_11_0_arm64.whl
Size 4.4 MB
Tags CPython 3.10 abi3 macOS 11.0+ ARM64
SHA-256 checksum
How to use checksums
ac9195a7149fa719727d58ec86523acecdf1d07025355a43288797b45065a249
BLAKE2b-256 checksum
How to use checksums
59de96293369b557ca127473732c99d23d0c6bb02c496e1b9fb28240dba84f92
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via maturin/1.16.0

Release files / polars_grouper-0.7.0-cp310-abi3-macosx_10_12_x86_64.whl

Download URL polars_grouper-0.7.0-cp310-abi3-macosx_10_12_x86_64.whl
Size 4.7 MB
Tags CPython 3.10 abi3 macOS 10.12+ x86-64
SHA-256 checksum
How to use checksums
f479d681359970a62263e03c31facd4901e13c07b445ef99eb29a20d9fbb721d
BLAKE2b-256 checksum
How to use checksums
735587ac5812a4c2470d3a492085a7f218600493a9c03c326b2d1772225a2c9c
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via maturin/1.16.0

Security for polars-grouper 0.7.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page