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.3.tar.gz (765.3 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.3-py3-none-any.whl (143.7 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: grouprec-0.0.3.tar.gz
  • Upload date:
  • Size: 765.3 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.3.tar.gz
Algorithm Hash digest
SHA256 ef1405f1ac4935912aa03c8750d1c84d90b8c0321b6c99b47f4a29f072d3fcfd
MD5 bfce92e1a1abcdfffb69dd35d17f23eb
BLAKE2b-256 3225ea0bc690ce27e57270015028eef0796f507f929990da96e7f56645306943

See more details on using hashes here.

File details

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

File metadata

  • Download URL: grouprec-0.0.3-py3-none-any.whl
  • Upload date:
  • Size: 143.7 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.3-py3-none-any.whl
Algorithm Hash digest
SHA256 0ecff5f3699edda25264f4548f985239b22c953d7b2de1616d0cd29d134ed847
MD5 e686a237ad43f79fcf45ca37fe546de5
BLAKE2b-256 4d9079e52d0228ccf3f0c93913f15415db74bd0628ac2c9bea0c004dd5383866

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