Skip to main content

Iterative Positioning via Logistic Regression Embedding

Project description

IXPLORE

Iterative Positioning via Logistic Regression Embedding: A Python package for embedding users and items of political questionnaires in a shared 2D latent space.

IXPLORE jointly learns a posterior distribution for each user and a logistic regression model for each question. This can be used to visualize the political landscpae in a two dimensional, interpretable space. In inference, it can be used for missing value imputation and answer prediction.

Features

  • User Embedding: Compute posterior distributions over user positions using observed reactions
  • Item Models: Define decision boundaries in the latent space for each item by learning logistic regression models
  • Iterative Refinement: Jointly optimize user embeddings and item models through iterative updates
  • Flexible Initialization: Initialize embeddings via PCA, random values, or load pretrained embeddings
  • Missing Data Handling: Robust to missing values in the user-item reaction matrix
  • Answer Imputation: Predict missing answers based on learned user positions
  • New User Embedding: Embed new users based on their responses and obtain optimal positions with uncertainty quantification
  • Visualization Tools: Built-in plotting functions for embeddings, posteriors, and item decision boundaries

Installation

pip install ixplore

Or install from source:

git clone https://github.com/fybach/ixplore.git
cd ixplore
pip install -e .

Quick Start

import pandas as pd
from ixplore import IXPLORE

# Load reaction data (users × items matrix, values in [0, 1])
reactions = pd.read_csv('../data/synthetic_reactions.csv', index_col=0)

# Initialize and fit the model
model = IXPLORE(reactions, pca_initialization=True)

# Get user embeddings
embedding  = model.get_embedding()        # User positions (N × 2)
parameters = model.get_item_parameters()  # Item parameters (K × 3)

# Embed a new user based on their answers
new_user_answers = pd.Series({'Q1': 0.8, 'Q2': 0.2, 'Q3': 0.6}, name='new_user')
position = model.embed_new_user(new_user_answers)

# Predict all answers for a user
predicted = model.predict_all_answers(new_user_answers)

Usage

Custom Configuration

import numpy as np

model = IXPLORE(
    reactions,
    prior_mean=np.array([0, 0]),                # Prior center
    prior_cov=np.array([[0.1, 0], [0, 0.1]]),   # Prior covariance
    sampling_resolution=200,                    # Grid resolution for posteriors
    xlimits=(-1, 1),                            # X-axis bounds
    ylimits=(-1, 1),                            # Y-axis bounds
    pca_initialization=True,                    # Initialize with PCA
    random_state=17                             # For reproducibility
)

Loading Pretrained Models

# Load pretrained embedding and model parameters
model = IXPLORE(
    reactions,
    pretrained_embedding='../data/synthetic_embedding.csv',
)

Visualization

from ixplore.visualization import plot_embedding, plot_overview

# Plot user embeddings
plot_embedding(model.get_embedding(), colors='blue')

# Plot comprehensive overview
plot_overview(model, n=0, q='Q1', colors=user_colors)

API Reference

IXPLORE Class

Constructor Parameters

Parameter Type Default Description
reactions pd.DataFrame required User-item reaction matrix (users as index, items as columns)
prior_mean np.ndarray [0, 0] Mean of the prior distribution
prior_cov np.ndarray [[0.1, 0], [0, 0.1]] Covariance of the prior distribution
sampling_resolution int 200 Grid resolution for posterior computation
xlimits tuple (-1, 1) X-axis limits of the latent space
ylimits tuple (-1, 1) Y-axis limits of the latent space
pca_initialization bool True Initialize embeddings with PCA
random_state int 0 Random seed for reproducibility

Key Methods

Method Description
iterate(n_iterations) Run n iterations of posterior fitting and model updating
fit_posteriors() Compute posterior distributions for all users
fit_models() Fit logistic regression models for all items
get_embedding() Return current user embeddings as DataFrame
get_item_parameters() Return item model parameters
embed_new_user(answers) Embed a new user given their answers
predict_all_answers(answers) Predict answers for all items given partial answers
impute_remaining_answers(answers) Impute missing answers for a user
evaluate() Return MAE and accuracy on training data

Dependencies

  • numpy
  • pandas
  • scikit-learn
  • scipy
  • matplotlib

License

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

Citation

If you use IXPLORE in your research, please cite:

@software{bachmann2026ixplore,
  author       = {Bachmann, Fynn},
  title        = {IXPLORE: Iterative Positioning via Logistic Regression Embedding},
  year         = {2026},
  publisher    = {GitHub},
  url          = {https://github.com/fybach/ixplore}
}

Or in text format:

Bachmann, F. (2026). IXPLORE: Iterative Positioning via Logistic Regression Embedding. GitHub. https://github.com/fybach/ixplore

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

ixplore-0.1.0.tar.gz (14.2 kB view details)

Uploaded Source

Built Distribution

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

ixplore-0.1.0-py3-none-any.whl (13.0 kB view details)

Uploaded Python 3

File details

Details for the file ixplore-0.1.0.tar.gz.

File metadata

  • Download URL: ixplore-0.1.0.tar.gz
  • Upload date:
  • Size: 14.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.0

File hashes

Hashes for ixplore-0.1.0.tar.gz
Algorithm Hash digest
SHA256 13231a3b369b81da37e002994f589f786fb63cb21ccfdd007eb3134a6517ec9b
MD5 c7fe28be253f46f32f8163155751e352
BLAKE2b-256 0b86d68200e87dd66af5417011dc2128d3489f6061d7d16eb5e3404b8cce3c04

See more details on using hashes here.

File details

Details for the file ixplore-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: ixplore-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 13.0 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.0

File hashes

Hashes for ixplore-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 4bc7dc22c045715787e26440ea9516d5778baf66db932ede4f61aa0a40e4ac43
MD5 1d9e16feb91ecf33986ee5a6ec870f43
BLAKE2b-256 69d8188ac75cd1370fc8a19d3d4f62d609b287853cc645cc7ef91bb961ebbb1f

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