Skip to main content

A high-performance Python package for estimating latent-class conditional logit models.

Project description

LCL: Latent-Class Conditional Logit Estimation in Python

PyPI version Python 3.10+ License: MIT

LCL is a high-performance Python package for estimating latent-class conditional logit models.

Built for researchers and econometricians handling large discrete choice datasets, LCL employs JAX for GPU-accelerated gradient descent and Just-In-Time (JIT) compilation, alongside Polars for lightning-fast data management.

🚀 Features

  • Blazing Fast Estimation: Core likelihood functions are written in pure JAX, allowing for seamless hardware acceleration (CPU/GPU/TPU) and automatic differentiation.
  • Modern Data Handling: Native support for Polars DataFrames, avoiding the memory overhead and bottlenecking of traditional pandas pipelines.
  • Fail-Fast Type Checking: Powered by jaxtyping and beartype, LCL strictly enforces tensor shapes and data types at runtime. If you add an unsupported dimension to your design matrix, LCL catches it immediately with a readable error—no more cryptic JAX compilation tracebacks!

📦 Installation

Although the package is imported as lcl, it is hosted on PyPI as lcl-choice.

pip install lcl-choice

Note: If you plan to run LCL on a GPU, ensure you install the correct GPU-enabled version of JAX for your system.

💡 Quickstart

Here is a minimal example of estimating a basic latent-class logit model using synthetic discrete choice data.

import polars as pl
import jax.numpy as jnp
import lcl

# 1. Load your choice data
df = pl.DataFrame({
    "chooser_id": [1, 1, 2, 2],
    "alt_id": [1, 2, 1, 2],
    "choice": [1, 0, 0, 1],
    "price": [10.5, 12.0, 9.5, 11.0],
    "quality": [4, 5, 3, 5]
})

# 2. Format the data into JAX arrays
# (Assuming a utility function where users choose between alternatives based on price and quality)
X = jnp.array(df.select(["price", "quality"]).to_numpy())
choices = jnp.array(df["choice"].to_numpy())

# 3. Initialize and fit the model
# Estimate a model with 2 distinct latent consumer classes
model = lcl.LatentClassConditionalLogit(n_classes=2)
results = model.fit(X, choices)

print(results.summary())

🗺️ Roadmap & Future Developments

LCL is under active development. Although the core estimation engine is functional, we are actively working on expanding the package's accessibility and feature set. Upcoming milestones include:

  • Model Selection: How many latent classes genuinely reflect your data? We are developing a blocked cross-validation utility to let your data speak for themselves.
  • Comprehensive Documentation: Detailed tutorials and mathematical appendices are in the works.
  • Companion Paper: A scholarly working paper detailing the econometric framework, hardware benchmarking, and Monte Carlo simulations is currently in preparation.

Feature Requests: If there are specific constraints, optimization routines, or post-estimation tools you would like to see, please feel free to open a Feature Request on our GitHub Issues page!

🛠️ Development & Contributing

We welcome contributions! LCL uses uv for modern, isolated dependency management.

# Clone the repository
git clone https://github.com/zeyveld/latent-class-conditional-logit.git
cd latent-class-conditional-logit

# Sync the virtual environment and install dev dependencies
uv sync --all-extras --dev

# Run the test suite
uv run pytest tests/

🤝 Acknowledgments

In addition to the developers behind JAX, Polars, Beartype, and Jaxtyping, we are especially grateful to the creators of the xlogit package (Cristian Arteaga, JeeWoong Park, Prithvi Bhat Beeramoole, and Alexander Paz). Their highly efficient conditional logit logic profoundly influenced this package.

📝 Citation

If you use LCL in your research or publications, please consider citing it:

@software{lcl_2026,
  author = {Jeffries, Anna and Zeyveld, Andrew},
  title = {LCL: Latent-Class Conditional Logit Estimation in Python},
  year = {2026},
  url = {https://github.com/zeyveld/latent-class-conditional-logit}
}

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

lcl_choice-0.1.19.tar.gz (146.1 kB view details)

Uploaded Source

Built Distribution

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

lcl_choice-0.1.19-py3-none-any.whl (41.3 kB view details)

Uploaded Python 3

File details

Details for the file lcl_choice-0.1.19.tar.gz.

File metadata

  • Download URL: lcl_choice-0.1.19.tar.gz
  • Upload date:
  • Size: 146.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.9.9 {"installer":{"name":"uv","version":"0.9.9"},"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

Hashes for lcl_choice-0.1.19.tar.gz
Algorithm Hash digest
SHA256 6955841d165ba93d99556d3b1c4ae60b05654c83d2e5c8bfc0a30f913ad2f58f
MD5 7d697baa29efaed2bb43e1557683dfcd
BLAKE2b-256 b13259cec5bf198439b382e95edabd0312b7c3d455f8d12b9ef5e27eee1e9486

See more details on using hashes here.

File details

Details for the file lcl_choice-0.1.19-py3-none-any.whl.

File metadata

  • Download URL: lcl_choice-0.1.19-py3-none-any.whl
  • Upload date:
  • Size: 41.3 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.9.9 {"installer":{"name":"uv","version":"0.9.9"},"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

Hashes for lcl_choice-0.1.19-py3-none-any.whl
Algorithm Hash digest
SHA256 6e8e3d0909c18a09b54373c250dbec62c49afbd019bc46c6bc2bafa0862ab3d7
MD5 de7ccd5929ee2fdf722e4a2dd4311078
BLAKE2b-256 d6de5dff530998a772b6187b25a3d74c541cba36c7a3ffe80a47258627b7a50b

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