Python port of the seminr R package: PLS-SEM and covariance-based SEM (CBSEM/CFA)
Project description
seminr (Python)
A Python port of the seminr R package for structural equation modeling: PLS-SEM (partial least squares) and CBSEM/CFA (covariance-based SEM / confirmatory factor analysis).
The goal is numerical parity with seminr on the bundled mobi dataset —
1e-5 against R-generated golden fixtures for PLS quantities, and tiered
tolerances for CBSEM (which reimplements lavaan's ML/MLR estimator from
scratch, matching lavaan 0.6-21). The public API mirrors seminr's R names.
Built one vertical slice at a time; the port is now functionally complete.
Installation
pip install seminr # or: uv add seminr
pip install "seminr[pandas]" # optional: pandas DataFrame input + .to_dataframe()
Requires Python 3.11+. Runtime dependencies are NumPy and SciPy only.
Status
Functionally complete. The full non-plotting seminr surface is implemented
and matches seminr on the bundled mobi dataset (1e-5 for PLS quantities;
tiered tolerances for CBSEM):
- Specification DSL — constructs, composite/reflective/higher-order
composites, all three interaction methods (product-indicator, orthogonal,
two-stage) and quadratic terms, item-error associations,
as_reflective/higher_reflective, andcsem2seminr/lavaan2seminrsyntax import. - PLS-SEM —
estimate_pls(PLSc for reflective constructs, two-stage higher-order constructs, interactions),bootstrap_model(with t-values, percentile CIs, mediation helpers), andrerun. - Assessment —
summarize()for every model kind, reliability (alpha / rhoA / rhoC / AVE), validity (HTMT, Fornell-Larcker, cross-loadings, VIFs), f², AIC/BIC, and descriptives. - PLSpredict (
predict_pls, directpredict) and PLS-MGA (estimate_pls_mga). - CBSEM / CFA —
estimate_cbsem/estimate_cfa, a from-scratch ML/MLR estimator matchinglavaan::sem/cfa(std.lv=TRUE): LISREL model, analytic gradient, ~21 fit measures, Huber-White robust SEs, Yuan-Bentler-Mplus scaled test, and ten Berge factor scores.
Bootstrap, PLSpredict, and MGA accept an opt-in cores= argument for
multiprocess parallelism. Out of scope: the plotting/presentation layer. See
.claude/plans/PLAN.port-seminr.md for the
full slice-by-slice history and .claude/FUTURE.md for
deferred items.
Usage
from seminr import (
constructs, composite, multi_items,
relationships, paths, interaction_term,
estimate_pls, bootstrap_model,
)
# The ECSI mobi dataset ships with the package:
from seminr.datasets import load_mobi
mobi = load_mobi()
# ...or bring your own as a pandas DataFrame or a (column_names, 2-D array) pair.
measurement_model = constructs(
composite("Image", multi_items("IMAG", [1, 2, 3, 4, 5])),
composite("Expectation", multi_items("CUEX", [1, 2, 3])),
composite("Satisfaction", multi_items("CUSA", [1, 2, 3])),
interaction_term("Image", "Expectation"), # a product-indicator moderation
)
structural_model = relationships(
paths(["Image", "Expectation", "Image*Expectation"], "Satisfaction"),
)
model = estimate_pls(mobi, measurement_model, structural_model)
image_path = model.path_coef.get("Image", "Satisfaction") # path coefficient
r2 = model.r_squared.get("Rsq", "Satisfaction") # structural R-squared
# Bootstrap for standard errors and t-values (see the reproducibility note below).
boot = bootstrap_model(model, nboot=200, seed=123)
boot_sd = boot.paths_descriptives.get("Image", "Satisfaction Boot SD")
t_value = image_path / boot_sd
Result matrices are NamedMatrix values: index them by row/column name with
.get(row, col), or reach the underlying float64 array via .values.
Attribution
- seminr (R, GPL-3.0) by Soumya Ray, Nicholas Danks, and contributors — the authoritative reference for behavior and the source of every golden fixture in this repository.
- seminr-ts (TypeScript, GPL-3.0) — a completed, fixture-verified port of the same package. Its module layout, algorithm digests, and fixtures are reused directly here.
Bootstrap reproducibility
bootstrap_model(model, nboot=..., seed=...) uses a default resampler backed by
NumPy's Generator(PCG64(seed)). It is deterministic within Python for a given
seed, but it is not identical to seminr's R Mersenne-Twister resampling, so
its replication indices — and therefore the resulting bootstrap descriptives —
differ from R even at the same nominal seed. For exact parity with a specific R
run, inject the resample indices directly: bootstrap_model(model, nboot=n, indices=matrix), where matrix is an nboot x n array of 0-based row indices
(the parity tests feed R's exported index matrix this way). A custom resampler
can also be supplied. This mirrors the seminr-ts port's decision (its plan Q3/Q5).
Performance
The numerical kernel is backed by NumPy/SciPy (BLAS), so estimation, bootstrap,
PLSpredict, and MGA run faster than seminr's R implementation on the mobi
benchmarks — including seminr's own optimized branch — with no hand-tuned
Python. bootstrap_model, predict_pls, and estimate_pls_mga accept an
opt-in cores=N argument that fans replications/folds/groups out across
processes; results are bit-identical to the sequential path. Note that on small
models (like mobi, where a single estimation is sub-millisecond) the process
pool's start-up and pickling overhead can make cores= slower than the
default sequential path — reach for it when nboot, the sample size, or the
per-replication cost is large enough to amortize that overhead. The measurement
harness lives in benchmark/.
License
GPL-3.0-only, as a derivative work of the GPL-3 seminr package.
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 seminr-0.1.0.tar.gz.
File metadata
- Download URL: seminr-0.1.0.tar.gz
- Upload date:
- Size: 1.2 MB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
7a039ae6710cd89bc38cbd71030de0809a695b38da935237cd506af055693c83
|
|
| MD5 |
0e52d255f19bccd045ecc32082124219
|
|
| BLAKE2b-256 |
78f89d6a2e7f14cce2c67928406b81ae2074553ea3cb2680ae22ef4334b8eba6
|
Provenance
The following attestation bundles were made for seminr-0.1.0.tar.gz:
Publisher:
release.yml on sem-in-r/seminr-py
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
seminr-0.1.0.tar.gz -
Subject digest:
7a039ae6710cd89bc38cbd71030de0809a695b38da935237cd506af055693c83 - Sigstore transparency entry: 2116645441
- Sigstore integration time:
-
Permalink:
sem-in-r/seminr-py@8bf41507a237f91cccd391999c16f94d3d1227db -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/sem-in-r
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@8bf41507a237f91cccd391999c16f94d3d1227db -
Trigger Event:
push
-
Statement type:
File details
Details for the file seminr-0.1.0-py3-none-any.whl.
File metadata
- Download URL: seminr-0.1.0-py3-none-any.whl
- Upload date:
- Size: 132.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
bc323e746e1e755539bc70c83033acb4e32657e3335e12d5eacd94809cd1afa4
|
|
| MD5 |
141e36b901094dcc5c763e8d1f2d0da9
|
|
| BLAKE2b-256 |
a168eef6efdd88725f464e2f82c6583594d81c3e9b91c10df424491619c9ee0e
|
Provenance
The following attestation bundles were made for seminr-0.1.0-py3-none-any.whl:
Publisher:
release.yml on sem-in-r/seminr-py
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
seminr-0.1.0-py3-none-any.whl -
Subject digest:
bc323e746e1e755539bc70c83033acb4e32657e3335e12d5eacd94809cd1afa4 - Sigstore transparency entry: 2116645621
- Sigstore integration time:
-
Permalink:
sem-in-r/seminr-py@8bf41507a237f91cccd391999c16f94d3d1227db -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/sem-in-r
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@8bf41507a237f91cccd391999c16f94d3d1227db -
Trigger Event:
push
-
Statement type: