Skip to main content

Domain-agnostic LOOPR ranking engine library

Project description

LOOPR

loopr is a domain-agnostic ranking library for event-based competition data. It is built for the common real-world case where outcomes are recorded for groups or teams, but the thing you actually want to rank is individuals. Give it event results plus who belonged to or appeared for each group, and it decomposes that team-shaped evidence into entity-level rankings.

The stable public API is:

  • rank_entities(...) for the one-shot ranking path
  • prepare_rank_inputs(...) for validating neutral input tables
  • LOOPREngine when you want engine state, diagnostics, or LOO analysis
  • ExposureLogOddsConfig when you need to override defaults

LOOPREngine is currently an alias for ExposureLogOddsEngine.

Installation

PyPI distribution name:

pip install loopr-ranking

Import path remains:

import loopr

For local development:

pip install -e .
pip install -e .[dev]

If you use uv:

uv sync --extra dev

Requires Python 3.10+.

Docker Build

The wheel and sdist release path is also available through the multi-stage Dockerfile.

Run tests and quickstart smoke inside Docker:

docker build --target test .

Build distributable artifacts into a local directory:

docker buildx build --target artifacts --output type=local,dest=dist .

Quick Start

Command line:

loopr rank \
  --matches examples/quickstart/matches.csv \
  --participants examples/quickstart/participants.csv \
  --appearances examples/quickstart/appearances.csv \
  --output rankings.csv

If the package is installed and you prefer the module entrypoint:

python -m loopr rank \
  --matches examples/quickstart/matches.csv \
  --participants examples/quickstart/participants.csv \
  --appearances examples/quickstart/appearances.csv \
  --output rankings.csv

Python:

import polars as pl

from loopr import rank_entities

matches = pl.read_csv("examples/quickstart/matches.csv")
participants = pl.read_csv("examples/quickstart/participants.csv")
appearances = pl.read_csv("examples/quickstart/appearances.csv")
entities = pl.read_csv("examples/quickstart/entities.csv")

rankings = rank_entities(
    matches,
    participants,
    appearances=appearances,
)

print(
    rankings.join(entities, on="entity_id")
    .select(["entity_id", "entity_name", "score", "exposure"])
    .head(10)
)

If your spreadsheets look like this, you are on the happy path.

matches.csv

event_id match_id winner_id loser_id completed_at
1 10 100 200 1700000000
1 11 100 300 1700003600
1 12 300 200 1700007200

participants.csv

event_id group_id entity_id
1 100 1
1 100 2
1 200 3
1 200 4
1 300 5
1 300 6

appearances.csv (optional)

event_id match_id entity_id group_id
1 10 1 100
1 10 2 100
1 10 3 200
1 10 4 200

If you omit appearances, loopr assumes the full event-level group roster participated in each result.

The example files shown above live in the repository under examples/quickstart/. They are not installed with the wheel. After installing the package, you can regenerate them with:

python -m loopr.example_data --output-dir examples/quickstart

Recommended Defaults

For most users, the right starting point is:

  • rank_entities(...)
  • default configuration
  • appearances included whenever available

Treat the output as a ranking signal, not a calibrated probability-like score. Tune only after you have an external validation target or a clear operational reason. The deeper guidance lives in the repository docs under docs/defaults-and-recipes.md and docs/validation-harness.md.

Public Input Shape

The main public path expects binary group-result inputs and returns individual/entity rankings.

Matches

Required columns:

  • event_id
  • match_id
  • winner_id
  • loser_id

Optional columns:

  • completed_at
  • created_at
  • walkover

Participants

Required columns:

  • event_id
  • group_id
  • entity_id

Appearances

Optional per-match participation data:

  • event_id
  • match_id
  • entity_id
  • optional group_id

If appearances are present, loopr uses them to determine who actually played in a result instead of assuming the full roster participated.

Stable API

For published usage, prefer these as the supported surface:

  • rank_entities(...)
  • loopr rank
  • prepare_rank_inputs(...)
  • LOOPREngine
  • ExposureLogOddsConfig

The public API is neutral-schema-only. Inputs using the older tournament / team / user naming are not part of the supported public surface.

Engine Summary

LOOPREngine / ExposureLogOddsEngine

The recommended default. It is volume-neutral, exposure-based, supports time decay and inactivity decay, and includes exact leave-one-match-out analysis.

TickTockEngine

An iterative tournament-influence engine that alternates between entity rating updates and tournament-strength updates.

TTLEngine

A hybrid flow that uses tick-tock tournament influence updates with a rating backend such as the log-odds backend.

Documentation

README is the general entrypoint. The advanced docs live in the repository under docs/, including:

  • docs/README.md: advanced docs index
  • docs/input-patterns.md: schema guidance and normalization
  • docs/how-loopr-works.md: technical walkthrough
  • docs/mathematical-machinery.md: equations and intuition
  • docs/engines-and-configuration.md: engine comparison and configuration
  • docs/defaults-and-recipes.md: starting setup and baseline recipes
  • docs/validation-and-benchmarks.md: evaluation guidance
  • docs/validation-harness.md: reusable validation contract
  • docs/ablations.md: ingredient-level comparison design
  • docs/case-studies/README.md: applied examples
  • docs/analysis-and-diagnostics.md: diagnostics and LOO analysis

Common Next Steps

  • Use prepare_rank_inputs(...) when you want schema validation before ranking or when debugging normalized inputs.
  • Pass appearances when match-level participation differs from the stored roster.
  • Start with rank_entities(...) and the default config, then validate before tuning; see docs/defaults-and-recipes.md in the repository.

Development

Run the test suite with:

pytest -q

The codebase uses Polars, NumPy, and SciPy for the main compute path.

License

Apache-2.0. See LICENSE.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

loopr_ranking-0.0.1.tar.gz (78.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

loopr_ranking-0.0.1-py3-none-any.whl (71.0 kB view details)

Uploaded Python 3

File details

Details for the file loopr_ranking-0.0.1.tar.gz.

File metadata

  • Download URL: loopr_ranking-0.0.1.tar.gz
  • Upload date:
  • Size: 78.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.10

File hashes

Hashes for loopr_ranking-0.0.1.tar.gz
Algorithm Hash digest
SHA256 fac0acf353edbfc1f76055cd53b1a0db8856039d0ed2514434f6ada30e91ec71
MD5 6e85dbbaf26120a12e483f92c2f6a73b
BLAKE2b-256 b5ad5cca250744c9795afdcf43bf0e0490f21ee699fa1966c28e42b9021cec25

See more details on using hashes here.

File details

Details for the file loopr_ranking-0.0.1-py3-none-any.whl.

File metadata

  • Download URL: loopr_ranking-0.0.1-py3-none-any.whl
  • Upload date:
  • Size: 71.0 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.10

File hashes

Hashes for loopr_ranking-0.0.1-py3-none-any.whl
Algorithm Hash digest
SHA256 7ae7570b78dc0693653530ca08e72be4022ee86a737f265ef070164693127284
MD5 a6bd777a8d854e64e8400621f472c97b
BLAKE2b-256 d1638513736c24fdab9d5b030977ac25e1d3c103fde5d2844989cf99ab5ff6eb

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page