A Python library for quantitative reasoning.
Project description
formative
Python library for quantitative reasoning.
Requirements
- Python 3.10+
Installation
pip install formative-ds
Docs
Comprehensive documentation is available at docs.getformative.dev.
Usage
Causal estimation
Every analysis follows the same four steps: assume, estimate, refute, decide.
from formative.causal import DAG, OLSObservational
# 1. Encode your causal assumptions as a DAG
dag = DAG()
dag.assume("ability").causes("education", "income")
dag.assume("education").causes("income")
# 2. Estimate the causal effect
result = OLSObservational(dag, treatment="education", outcome="income").fit(df)
print(result.summary())
# 3. Refute: stress-test the result's assumptions
print(result.refute(df).summary())
# 4. Decide: is the treatment worth acting on?
print(result.decide(cost=8, benefit=15))
Confounders declared in the DAG are controlled for automatically. If a confounder is absent from the dataframe, an IdentificationError is raised before any estimation runs. Some estimators go further at step 4 — per-group decisions, or learning a treatment rule with learn_policy().
Decision rules
from formative.game import maximin, maximax, hurwicz, laplace, minimax
outcomes = {
"stocks": {"recession": -20, "stagnation": 5, "growth": 30},
"bonds": {"recession": 5, "stagnation": 5, "growth": 7},
"cash": {"recession": 2, "stagnation": 2, "growth": 2},
}
maximin(outcomes).solve() # safest choice (best worst case)
maximax(outcomes).solve() # most optimistic (best best case)
hurwicz(outcomes, alpha=0.5).solve() # blend of optimism and pessimism
laplace(outcomes).solve() # highest average payoff
minimax(outcomes).solve() # lowest worst-case regret
See online documentation at docs.getformative.dev for more examples and details.
Local development
Requires uv.
git clone https://github.com/maxpagels/formative
cd formative
uv sync --dev
This creates a .venv, installs all dependencies, and installs the package in editable mode.
Releasing a new version
make release BUMP=patch # 0.1.0 → 0.1.1 (bug fixes)
make release BUMP=minor # 0.1.0 → 0.2.0 (new features)
make release BUMP=major # 0.1.0 → 1.0.0 (breaking changes)
One command does everything: bumps the version in pyproject.toml and uv.lock
(commit + tag), builds the docs, snapshots them into site/<major.minor>/ (the versioned
docs site Vercel serves statically), and pushes with tags — which triggers the publish to
PyPI. It refuses to run if the working tree is dirty or uv.lock is out of date.
Running tests
uv run pytest
Importing without installing
To use formative from a script outside this repo without installing it, either prepend the path at runtime:
import sys
sys.path.insert(0, "/path/to/formative")
from formative.causal import DAG, OLSObservational
Or set PYTHONPATH before running:
PYTHONPATH=/path/to/formative python your_script.py
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 formative_ds-2.2.1.tar.gz.
File metadata
- Download URL: formative_ds-2.2.1.tar.gz
- Upload date:
- Size: 15.7 MB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
21492ae368f731d1091d06d27a052f811e2ca556afda79c1c0a3365aa368349c
|
|
| MD5 |
6a83134f8d3cdffc791e2fa9b6dd69cf
|
|
| BLAKE2b-256 |
783800fd9879cd1032907e019a028bcf9626e1de9532891c44538eaf6ef047a1
|
Provenance
The following attestation bundles were made for formative_ds-2.2.1.tar.gz:
Publisher:
publish.yml on maxpagels/formative
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
formative_ds-2.2.1.tar.gz -
Subject digest:
21492ae368f731d1091d06d27a052f811e2ca556afda79c1c0a3365aa368349c - Sigstore transparency entry: 2142724565
- Sigstore integration time:
-
Permalink:
maxpagels/formative@cc05b6f6861523535ca9389259983cc84d6e290f -
Branch / Tag:
refs/tags/v2.2.1 - Owner: https://github.com/maxpagels
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@cc05b6f6861523535ca9389259983cc84d6e290f -
Trigger Event:
push
-
Statement type:
File details
Details for the file formative_ds-2.2.1-py3-none-any.whl.
File metadata
- Download URL: formative_ds-2.2.1-py3-none-any.whl
- Upload date:
- Size: 69.4 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 |
0bc204d3e15240d52c380c798901a338ffe3524459aeeb39fbd671fbe1ad58b8
|
|
| MD5 |
698e1cf13e9da2e8952e5c0f908cc1be
|
|
| BLAKE2b-256 |
b82d9591c8147218b3704457a5321ac817ea82c331ae3b6332c8702305c94af8
|
Provenance
The following attestation bundles were made for formative_ds-2.2.1-py3-none-any.whl:
Publisher:
publish.yml on maxpagels/formative
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
formative_ds-2.2.1-py3-none-any.whl -
Subject digest:
0bc204d3e15240d52c380c798901a338ffe3524459aeeb39fbd671fbe1ad58b8 - Sigstore transparency entry: 2142724589
- Sigstore integration time:
-
Permalink:
maxpagels/formative@cc05b6f6861523535ca9389259983cc84d6e290f -
Branch / Tag:
refs/tags/v2.2.1 - Owner: https://github.com/maxpagels
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@cc05b6f6861523535ca9389259983cc84d6e290f -
Trigger Event:
push
-
Statement type: