A framework for characterizing and predicting pairwise comparisons using user clustering and matrix completion
Project description
Pairwise Comparison Framework
A Python framework for clustering users based on their pairwise comparison patterns and predicting missing comparisons via matrix completion.
This project was developed as part of a final thesis (TCC) at the Escola Politécnica, Universidade Federal do Rio de Janeiro (UFRJ).
Overview
The framework operates in two stages:
-
Clustering (Stage 1): Each user's pairwise comparisons are modeled as a weighted directed graph. Shortest-path-length matrices serve as structural preference signatures, a custom distance metric measures user similarity, and MDS + K-Means produces the final clusters.
-
Prediction (Stage 2): A sparse comparison matrix is built from all users' data. Matrix completion (Iterative SVD or KNN) fills in missing entries. Applying completion within each cluster improves prediction accuracy over a global model.
Installation
Requires Python 3.13+.
pip install pairwise-comparison-framework
Or with uv:
uv add pairwise-comparison-framework
For local development:
git clone https://github.com/henchaves/pairwise-comparison-framework.git
cd pairwise-comparison-framework
uv sync
Quick Start
Clustering
import pairwise_comparison_framework as pcf
clusterizer = pcf.Clusterizer()
clusterizer.load_data("data/sample/comparisons.json", "data/sample/labels.json")
# Visualize a user's preference graph
clusterizer.plot_graph("user_id", with_labels=True)
# Get item rankings via PageRank
clusterizer.get_ranking("user_id", with_labels=True)
# Cluster users
clusters = clusterizer.get_user_clusters(n_clusters=3)
# Assess cluster quality
clusterizer.get_silhouette_scores(n_clusters=3)
clusterizer.get_elbow_data(max_clusters=10)
clusterizer.plot_clusters(n_clusters=3)
Prediction
# Iterative SVD (default)
predictor = pcf.Predictor(impute_method="svd", impute_rank=1)
predictor.load_data("data/sample/comparisons.json", "data/sample/labels.json")
# Or KNN imputation
predictor = pcf.Predictor(impute_method="knn", impute_k=5)
predictor.load_data("data/sample/comparisons.json", "data/sample/labels.json")
# Predict missing comparisons
completed_matrix = predictor.predict()
# Controlled evaluation: global vs per-cluster
results = predictor.evaluate_global_vs_clusters(
clusters, n_rounds=50, test_size=0.2
)
Data Format
Comparisons (comparisons.json)
A JSON array of user comparison records. Each comparison score answers "How much more preferred is the first item over the second?":
2: first item much more preferred1: first item more preferred0: equally preferred (tie)-1: second item more preferred-2: second item much more preferred
[
{
"user_id": "user_01",
"comparisons": [
{
"first_item_id": "item_01",
"second_item_id": "item_02",
"score": 2
}
]
}
]
Labels (labels.json, optional)
A JSON array mapping item IDs to human-readable names:
[
{
"item_id": "item_01",
"label": "Oranges"
}
]
Notebooks
| Notebook | Description |
|---|---|
notebooks/clustering.ipynb |
Clustering pipeline demo with sample data |
notebooks/prediction.ipynb |
Prediction pipeline demo with sample data |
notebooks/epfl_analysis.ipynb |
Full analysis on the EPFL food preference dataset (private dataset, not included) |
Project Structure
pairwise-comparison-framework/
├── src/pairwise_comparison_framework/
│ ├── __init__.py # Exports Clusterizer, Predictor
│ ├── _base.py # Shared data loading logic
│ ├── models/ # Pydantic data models
│ ├── clusterizer/ # Stage 1: clustering pipeline
│ └── predictor/ # Stage 2: prediction pipeline
├── data/
│ └── sample/ # Small sample dataset (wine preferences)
└── notebooks/ # Jupyter notebooks
License
This project is licensed under the MIT License. See LICENSE for details.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file pairwise_comparison_framework-1.0.1.tar.gz.
File metadata
- Download URL: pairwise_comparison_framework-1.0.1.tar.gz
- Upload date:
- Size: 16.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.9.28 {"installer":{"name":"uv","version":"0.9.28","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f6f749790e15e4cf0346c749f25c303c7567ce0fd71fbe77ef6f37e32df0a698
|
|
| MD5 |
90c5556b68cae360dd532d85c2cab2f6
|
|
| BLAKE2b-256 |
6249490e3bb213339e3b946997b6ca6887c7339026c4d59c608a73bb8f160c6e
|
File details
Details for the file pairwise_comparison_framework-1.0.1-py3-none-any.whl.
File metadata
- Download URL: pairwise_comparison_framework-1.0.1-py3-none-any.whl
- Upload date:
- Size: 19.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.9.28 {"installer":{"name":"uv","version":"0.9.28","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b2e8e3006bbc35bdda21356c9685fe29bd20fe67bdf7c52dbee198c1f1468692
|
|
| MD5 |
f9b6ead7ea7e41f043402492e21e6971
|
|
| BLAKE2b-256 |
0912a2009694cf8706c2caa2eb6e0795c09a04d8aa7261a085ca4038f918bb52
|