Skip to main content

Group recommender systems for Python: results aggregation and profile aggregation as first-class citizens behind one API. Preference aggregation, group recommendation, fairness.

Project description

grouprec

Group recommender systems for Python — results aggregation and profile aggregation as first-class citizens behind one API.

Python versions License: MIT GitHub stars CI codecov docs code style: ruff

Keywords: group recommendation · group recommender systems · preference aggregation · collaborative filtering · fairness · Python.

Why this exists

One library for both kinds of group recommender — deep-learning SOTA models (AGREE, GroupIM, ConsRec, …) and classic, fairness-oriented aggregators (GFAR, EP-FuzzDA, RLProp/LTP, …) — behind one API, so you compare them head-to-head on the same data, splits, and metrics.

Group recommendation has split into two communities that rarely compare against each other (Peska et al., Bridging the Rift, UMAP 2025); general-purpose toolkits (LensKit, RecBole, Cornac, …) are single-user. grouprec bridges that — swap a results-aggregator for a deep model, score the same recommender under coupled vs decoupled, and put both in one leaderboard. See the design & the rift.

Install

pip install -e ".[full]"

Quickstart

import grouprec as gr
from grouprec import GroupRecommender, evaluate
from grouprec.backends import EASE          # or implicit_als(), Popularity(), lenskit(...)

data   = gr.make_blobs_dataset(seed=0)       # or gr.datasets.load("ml-1m") / your own Dataset
groups = gr.groups.synthetic(data, kind="similar", size=4, n=1000, metric="pearson")
folds  = gr.split.crossval(data, k=5, seed=0)

rec = GroupRecommender(EASE(), gr.aggregators.get("GFAR"), normalize="minmax")

report = evaluate(rec, data, groups, folds,
                  protocol=["coupled", "decoupled"],            # score both at once
                  metrics=["ndcg@10", "recall@10"],
                  group_aggregations=["mean", "min", "minmax"])  # the fairness lens
print(report.pivot())

Aggregators are plain numpy and usable standalone on a (n_members, n_items) matrix:

import numpy as np
from grouprec.aggregators import get
get("LTP").aggregate(np.array([[5., 3., 1.], [2., 3., 4.]]), k=2)

Bring your own recommender (wide algorithm coverage via adapters)

We don't reimplement single-user recommenders — we wrap the established frameworks so you inherit their entire model zoos, plus a few dependency-free built-ins. Any object with fit(dataset) + score(users, items=None) is a backend.

Backend How Algorithms
Built-in (no extra deps) Popularity, EASE, ItemKNN, Random popularity, EASE^R, item-kNN
implicit [implicit] gr.backends.implicit_als(factors=64), implicit_bpr(...) ALS, BPR
LensKit [lenskit] gr.backends.lenskit(ImplicitMFScorer(...)) ImplicitMF, BiasedMF, ItemKNN, UserKNN, EASE, SLIM, …
RecBole [recbole] gr.backends.recbole(model, dataset) (experimental) the full RecBole zoo

Deep group models ([torch])

Lazily imported, so import grouprec never pulls torch:

from grouprec.models import AGREE, GroupIM, ConsRec, make_synthetic_group_data
gd = make_synthetic_group_data(seed=0)
model = ConsRec(gd.groups, gd.group_interactions).fit(gd.dataset)
model.recommend(gd.groups[0], k=10)          # paradigm="profile" -> coupled group-level

Model zoo: NCFGroup, AGREE, GroupIM (InfoMax SSL), ConsRec (overlap/hypergraph/LightGCN consensus), HyperGroup (hierarchical hyperedge embedding), HHGR (double-scale self-supervised hypergraph), AlignGroup (InfoNCE member/group alignment) — each reviewed against its original repo. They plug into benchmark(..., level="sampled") and share the same coupled protocol as results-aggregators, so both families compare side by side.

Datasets (license-aware)

data = gr.datasets.load("ml-1m")             # auto-fetched, cached, parsed
data = gr.datasets.k_core(data, k=5)         # k-core / binarize / min-count preprocessing
print(gr.datasets.info("kgrec").license)     # every entry carries license + citation
gd   = gr.datasets.load_consrec("path/CAMRa2011")          # explicit-group benchmark
gd   = gr.datasets.load_yin(gr.datasets.fetch_yin(accept_license=True), "yelp")
Policy Datasets Behavior
auto MovieLens 100K/1M/25M/32M/latest/latest-small fetched for your own use (GroupLens permits research download; redistribution terms differ by release — 100K/1M forbid it, 25M/latest allow it under same terms)
auto_nc KGRec, Last.fm, Yelp-LA, Douban-SH non-commercial — fetched only after accept_license=True, citations surfaced
manual CAMRa2011, Mafengwo, Weeplaces redistribution unclear — load prints where to download

Licensing: The library code is released under MIT. Datasets are not relicensed by the library and remain subject to their upstream terms. The library does not bundle dataset files; for datasets with access restrictions or non-commercial terms, loading is enabled only when the user accepts the dataset-specific license or follows the upstream download instructions. Plus from_huggingface(...) / from_path(...) for anything else.

Benchmark & the rift

Score the same recommender under coupled vs decoupled and put both families on one board:

res = gr.benchmark(recs, tasks, protocols=["coupled", "decoupled"], metrics=["ndcg@10"])
res.to_csv("leaderboard.csv")                # tidy long-format
res.leaderboard("ndcg", k=10, protocol="coupled")     # ranking flips vs "decoupled"

Explore a group recommendation end-to-end in the interactive inspector — built on the 20-core of MovieLens ml-latest (204,257 users / 23,290 items / 32.2M ratings); every ranking is a real grouprec call (how it's built; regenerate with grouprec-build-inspector, needs [torch] — add --small for a quick, much smaller page off ml-latest-small).

What's inside

  • Aggregators (numpy core): ADD AVG LMS MUL MPL AVGNM BDC FAI, GFAR GreedyLM PAR SPGreedy EPFuzzDA (fairness), RLProp LTP PeriodicFAI EPFuzzDAWeighted SDAA SIAA (sequential).
  • Group formation: gr.groups.synthetic(kind="random|similar|divergent|outlier").
  • Evaluation: coupled / decoupled / sampled protocols; metrics at the per-member (ndcg/recall/hr/ar/… × mean/min/minmax/jain/zero) and per-list (novelty, list_coverage, register_list_metric) levels.
  • Reproducibility: gr.Experiment (seed + env + git SHA/dirty/diff + citations), gr.set_seed, gr.cite("ConsRec").

Extras at a glance

gr.cite("ConsRec")                            # BibTeX for any implemented method
gr.collect_citations(rec, dataset)            # auto-collect cites for what a run used
with gr.Experiment("run1", seed=42, cite=[rec, dataset]) as exp:  # cites auto-resolved
    ...                                       # writes runs/run1-<ts>/ on exit
gr.eval.register_metric("coverage", fn)       # custom per-member metric
gr.eval.register_list_metric("ild", fn)       # custom per-list metric

Contributing — researchers especially welcome

Published a group-rec method? Add it (small PR — CONTRIBUTING.md has copy-paste recipes for an aggregator / deep model / dataset / metric), or just link your repo in a port-request issue and we'll port it. Every method ships with its citation, so your work is credited wherever the library is used. Students & practitioners welcome too (good-first-issue).

Citation

If you use grouprec, please cite it (CITATION.cff) and the relevant method (gr.cite(...)). Docs: https://pdokoupil.github.io/grouprec.

A demo-track paper describing this toolkit is under review at RecSys 2026:

Patrik Dokoupil, Ludovico Boratto, and Ladislav Peska. GroupRec: A Unified Toolkit for Reproducible and Inspectable Group Recommendation Research.

License

MIT. Datasets retain their own licenses (see Datasets above).

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

grouprec-0.0.2.tar.gz (762.4 kB view details)

Uploaded Source

Built Distribution

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

grouprec-0.0.2-py3-none-any.whl (143.4 kB view details)

Uploaded Python 3

File details

Details for the file grouprec-0.0.2.tar.gz.

File metadata

  • Download URL: grouprec-0.0.2.tar.gz
  • Upload date:
  • Size: 762.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.3

File hashes

Hashes for grouprec-0.0.2.tar.gz
Algorithm Hash digest
SHA256 7008b8eefdd6a2743af0d5f1533a7cdbee53a66398eea5cde7daeee2b163cfe9
MD5 a6e074e725f5f9ca6799f88ff7b18b51
BLAKE2b-256 4124e95f2cc6af43c6700fe07f91f7c7699a50080c6010b3ce54cac6de5f1b54

See more details on using hashes here.

File details

Details for the file grouprec-0.0.2-py3-none-any.whl.

File metadata

  • Download URL: grouprec-0.0.2-py3-none-any.whl
  • Upload date:
  • Size: 143.4 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.3

File hashes

Hashes for grouprec-0.0.2-py3-none-any.whl
Algorithm Hash digest
SHA256 660bb01e01c1735a10d82c95cabd9db11b2a08487b27c2f786cec61635edfe66
MD5 a5a173ea69592dd07b7a45f236fa9f76
BLAKE2b-256 d106dd0d5d79873b743fb64d6e990a6e3d9854cbc7a3db99ff59ab8327fde266

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