signapy 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- signapy-0.1.0/.github/workflows/ci.yml +71 -0
- signapy-0.1.0/.github/workflows/publish.yml +85 -0
- signapy-0.1.0/.gitignore +30 -0
- signapy-0.1.0/CHANGELOG.md +48 -0
- signapy-0.1.0/CONTRIBUTING.md +63 -0
- signapy-0.1.0/LICENSE +21 -0
- signapy-0.1.0/PKG-INFO +419 -0
- signapy-0.1.0/README.md +380 -0
- signapy-0.1.0/docs/architecture.md +712 -0
- signapy-0.1.0/docs/assets/signapy-logo.png +0 -0
- signapy-0.1.0/docs/metrics.md +637 -0
- signapy-0.1.0/examples/binary_categorical_discovery.py +82 -0
- signapy-0.1.0/examples/mixed_categorical_continuous_discovery.py +121 -0
- signapy-0.1.0/examples/ordinal_binary_discovery.py +82 -0
- signapy-0.1.0/pyproject.toml +86 -0
- signapy-0.1.0/src/signapy/__init__.py +14 -0
- signapy-0.1.0/src/signapy/discovery/__init__.py +378 -0
- signapy-0.1.0/src/signapy/discovery/_frame.py +81 -0
- signapy-0.1.0/src/signapy/discovery/feature.py +318 -0
- signapy-0.1.0/src/signapy/discovery/value.py +253 -0
- signapy-0.1.0/src/signapy/metrics/__init__.py +24 -0
- signapy-0.1.0/src/signapy/metrics/association.py +603 -0
- signapy-0.1.0/src/signapy/metrics/lift.py +158 -0
- signapy-0.1.0/src/signapy/metrics/significance.py +106 -0
- signapy-0.1.0/src/signapy/profiling/__init__.py +9 -0
- signapy-0.1.0/src/signapy/profiling/types.py +39 -0
- signapy-0.1.0/src/signapy/py.typed +0 -0
- signapy-0.1.0/src/signapy/results/__init__.py +9 -0
- signapy-0.1.0/src/signapy/results/_plot.py +555 -0
- signapy-0.1.0/src/signapy/results/models.py +409 -0
- signapy-0.1.0/tests/test_association.py +126 -0
- signapy-0.1.0/tests/test_continuous_bins.py +164 -0
- signapy-0.1.0/tests/test_discovery.py +296 -0
- signapy-0.1.0/tests/test_lift.py +161 -0
- signapy-0.1.0/tests/test_mixed_discovery.py +428 -0
- signapy-0.1.0/tests/test_ordinal_discovery.py +309 -0
- signapy-0.1.0/tests/test_package.py +15 -0
- signapy-0.1.0/tests/test_point_biserial.py +322 -0
- signapy-0.1.0/tests/test_polars_discovery.py +216 -0
- signapy-0.1.0/tests/test_results.py +671 -0
- signapy-0.1.0/tests/test_significance.py +109 -0
- signapy-0.1.0/tests/test_spearman.py +312 -0
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
pull_request:
|
|
7
|
+
|
|
8
|
+
permissions:
|
|
9
|
+
contents: read
|
|
10
|
+
|
|
11
|
+
concurrency:
|
|
12
|
+
group: ${{ github.workflow }}-${{ github.ref }}
|
|
13
|
+
cancel-in-progress: true
|
|
14
|
+
|
|
15
|
+
jobs:
|
|
16
|
+
lint:
|
|
17
|
+
runs-on: ubuntu-latest
|
|
18
|
+
steps:
|
|
19
|
+
- uses: actions/checkout@v4
|
|
20
|
+
- uses: actions/setup-python@v5
|
|
21
|
+
with:
|
|
22
|
+
python-version: "3.12"
|
|
23
|
+
- name: Install package with dev dependencies
|
|
24
|
+
run: python -m pip install --upgrade pip && python -m pip install -e ".[dev]"
|
|
25
|
+
- name: Lint
|
|
26
|
+
run: ruff check .
|
|
27
|
+
- name: Check formatting
|
|
28
|
+
run: ruff format --check .
|
|
29
|
+
|
|
30
|
+
test:
|
|
31
|
+
runs-on: ubuntu-latest
|
|
32
|
+
strategy:
|
|
33
|
+
fail-fast: false
|
|
34
|
+
matrix:
|
|
35
|
+
python-version: ["3.10", "3.11", "3.12", "3.13", "3.14"]
|
|
36
|
+
steps:
|
|
37
|
+
- uses: actions/checkout@v4
|
|
38
|
+
- uses: actions/setup-python@v5
|
|
39
|
+
with:
|
|
40
|
+
python-version: ${{ matrix.python-version }}
|
|
41
|
+
- name: Install package with dev dependencies
|
|
42
|
+
run: python -m pip install --upgrade pip && python -m pip install -e ".[dev]"
|
|
43
|
+
- name: Verify import
|
|
44
|
+
run: python -c "import signapy; print(signapy.__version__)"
|
|
45
|
+
- name: Run tests
|
|
46
|
+
run: pytest
|
|
47
|
+
|
|
48
|
+
package:
|
|
49
|
+
runs-on: ubuntu-latest
|
|
50
|
+
steps:
|
|
51
|
+
- uses: actions/checkout@v4
|
|
52
|
+
- uses: actions/setup-python@v5
|
|
53
|
+
with:
|
|
54
|
+
python-version: "3.12"
|
|
55
|
+
- name: Build and validate distributions
|
|
56
|
+
run: |
|
|
57
|
+
python -m pip install --upgrade pip build twine
|
|
58
|
+
python -m build
|
|
59
|
+
python -m twine check dist/*
|
|
60
|
+
- name: Smoke-test the wheel in a clean environment
|
|
61
|
+
run: |
|
|
62
|
+
python -m venv "$RUNNER_TEMP/wheel-test"
|
|
63
|
+
"$RUNNER_TEMP/wheel-test/bin/python" -m pip install dist/*.whl
|
|
64
|
+
cd "$RUNNER_TEMP"
|
|
65
|
+
"$RUNNER_TEMP/wheel-test/bin/python" -c "import signapy; print(signapy.__version__); assert callable(signapy.discover)"
|
|
66
|
+
- name: Smoke-test the source distribution in a clean environment
|
|
67
|
+
run: |
|
|
68
|
+
python -m venv "$RUNNER_TEMP/sdist-test"
|
|
69
|
+
cd "$RUNNER_TEMP"
|
|
70
|
+
"$RUNNER_TEMP/sdist-test/bin/python" -m pip install "$GITHUB_WORKSPACE"/dist/*.tar.gz
|
|
71
|
+
"$RUNNER_TEMP/sdist-test/bin/python" -c "import signapy; print(signapy.__version__); assert callable(signapy.discover)"
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
name: Publish to PyPI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
release:
|
|
5
|
+
types: [published]
|
|
6
|
+
workflow_dispatch:
|
|
7
|
+
|
|
8
|
+
permissions:
|
|
9
|
+
contents: read
|
|
10
|
+
|
|
11
|
+
jobs:
|
|
12
|
+
build:
|
|
13
|
+
runs-on: ubuntu-latest
|
|
14
|
+
|
|
15
|
+
steps:
|
|
16
|
+
- name: Check out repository
|
|
17
|
+
uses: actions/checkout@v6
|
|
18
|
+
with:
|
|
19
|
+
persist-credentials: false
|
|
20
|
+
|
|
21
|
+
- name: Set up Python
|
|
22
|
+
uses: actions/setup-python@v6
|
|
23
|
+
with:
|
|
24
|
+
python-version: "3.12"
|
|
25
|
+
|
|
26
|
+
- name: Install build tools
|
|
27
|
+
run: python -m pip install build twine
|
|
28
|
+
|
|
29
|
+
- name: Build distributions
|
|
30
|
+
run: python -m build
|
|
31
|
+
|
|
32
|
+
- name: Validate distributions
|
|
33
|
+
run: python -m twine check dist/*
|
|
34
|
+
|
|
35
|
+
- name: Upload distributions
|
|
36
|
+
uses: actions/upload-artifact@v5
|
|
37
|
+
with:
|
|
38
|
+
name: python-package-distributions
|
|
39
|
+
path: dist/
|
|
40
|
+
|
|
41
|
+
publish:
|
|
42
|
+
if: github.event_name == 'release'
|
|
43
|
+
needs: build
|
|
44
|
+
runs-on: ubuntu-latest
|
|
45
|
+
|
|
46
|
+
environment:
|
|
47
|
+
name: pypi
|
|
48
|
+
url: https://pypi.org/p/signapy
|
|
49
|
+
|
|
50
|
+
permissions:
|
|
51
|
+
id-token: write
|
|
52
|
+
|
|
53
|
+
steps:
|
|
54
|
+
- name: Download distributions
|
|
55
|
+
uses: actions/download-artifact@v6
|
|
56
|
+
with:
|
|
57
|
+
name: python-package-distributions
|
|
58
|
+
path: dist/
|
|
59
|
+
|
|
60
|
+
- name: Publish distributions
|
|
61
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
62
|
+
|
|
63
|
+
publish-test:
|
|
64
|
+
if: github.event_name == 'workflow_dispatch'
|
|
65
|
+
needs: build
|
|
66
|
+
runs-on: ubuntu-latest
|
|
67
|
+
|
|
68
|
+
environment:
|
|
69
|
+
name: testpypi
|
|
70
|
+
url: https://test.pypi.org/p/signapy
|
|
71
|
+
|
|
72
|
+
permissions:
|
|
73
|
+
id-token: write
|
|
74
|
+
|
|
75
|
+
steps:
|
|
76
|
+
- name: Download distributions
|
|
77
|
+
uses: actions/download-artifact@v6
|
|
78
|
+
with:
|
|
79
|
+
name: python-package-distributions
|
|
80
|
+
path: dist/
|
|
81
|
+
|
|
82
|
+
- name: Publish distributions
|
|
83
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
84
|
+
with:
|
|
85
|
+
repository-url: https://test.pypi.org/legacy/
|
signapy-0.1.0/.gitignore
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# Byte-compiled / cache
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
.pytest_cache/
|
|
5
|
+
.ruff_cache/
|
|
6
|
+
.mypy_cache/
|
|
7
|
+
|
|
8
|
+
# Build artifacts
|
|
9
|
+
build/
|
|
10
|
+
dist/
|
|
11
|
+
*.egg-info/
|
|
12
|
+
.eggs/
|
|
13
|
+
|
|
14
|
+
# Virtual environments
|
|
15
|
+
.venv/
|
|
16
|
+
venv/
|
|
17
|
+
env/
|
|
18
|
+
|
|
19
|
+
# Coverage
|
|
20
|
+
.coverage
|
|
21
|
+
.coverage.*
|
|
22
|
+
htmlcov/
|
|
23
|
+
coverage.xml
|
|
24
|
+
|
|
25
|
+
# Notebooks / editors / OS
|
|
26
|
+
.ipynb_checkpoints/
|
|
27
|
+
.idea/
|
|
28
|
+
.vscode/
|
|
29
|
+
.DS_Store
|
|
30
|
+
uv.lock
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## 0.1.0 — first standard release (2026-11-05)
|
|
4
|
+
|
|
5
|
+
First release that is not an alpha. The API may still change before 1.0.
|
|
6
|
+
|
|
7
|
+
- Added the SignaPy logo (`docs/assets/signapy-logo.png`) to the README.
|
|
8
|
+
- `DiscoveryReport` gains `to_dict()`, a terminal `str()` table, a notebook
|
|
9
|
+
HTML repr, and `plot()`.
|
|
10
|
+
- `plot()` renders SignaPy's signature mosaic (tile width = support, colour =
|
|
11
|
+
lift) and returns a matplotlib `Figure`. Requires the optional `plot` extra.
|
|
12
|
+
- In Jupyter and Databricks, evaluating a report now shows the mosaic (inline
|
|
13
|
+
PNG) above the summary table; without matplotlib it shows the table alone.
|
|
14
|
+
- `print(report)` ends with a pointer to `to_dict()`, and the README has new
|
|
15
|
+
"Reading the report" and "Using SignaPy from an agent" sections.
|
|
16
|
+
- Mosaic conventions: rows are grouped by effect-size measure (V, ρ, r) and
|
|
17
|
+
sorted by absolute effect size within each group; value labels are cut to
|
|
18
|
+
20 characters; long feature names wrap onto extra lines and the row grows;
|
|
19
|
+
`plot(max_features=N)` draws only the strongest `N` features, and the
|
|
20
|
+
notebook view caps at 30. See the README's "Reading the mosaic".
|
|
21
|
+
- Every tile now carries its evidence: mid-width tiles show lift and support
|
|
22
|
+
percentage, and tiles too narrow for text are listed in a strip under the
|
|
23
|
+
rows (`feature: value lift × · support`, strongest departure from baseline
|
|
24
|
+
first, at most 12).
|
|
25
|
+
- Continuous features now get value-level evidence: `discover()` cuts each into
|
|
26
|
+
up to five quantile bins of roughly equal size (ties in the data can make
|
|
27
|
+
them unequal, and scarce rows mean fewer bins) and reports support, target
|
|
28
|
+
rate, baseline rate, and lift per bin, labelled as intervals like
|
|
29
|
+
`(38.4, 44.1]`. When ties collapse bins, the cut is retried with fewer bins,
|
|
30
|
+
and a feature with five or fewer distinct values gets one bin per value
|
|
31
|
+
(labelled `0`, `1`, ...). A single value holding more rows than one bin
|
|
32
|
+
(the zeros in a zero-inflated column) gets its own bin, labelled by the
|
|
33
|
+
value, with the rows below and above it binned separately. `FeatureResult.values`
|
|
34
|
+
is `None` only when a feature has too few rows or is constant.
|
|
35
|
+
|
|
36
|
+
## 0.1.0a2 — Polars input support
|
|
37
|
+
|
|
38
|
+
- `signapy.discover` accepts a Polars `DataFrame` (optional `polars` extra; no
|
|
39
|
+
PyArrow required). Results match equivalent pandas input.
|
|
40
|
+
|
|
41
|
+
## 0.1.0a1 — first public alpha
|
|
42
|
+
|
|
43
|
+
Initial release. The API is experimental and may change.
|
|
44
|
+
|
|
45
|
+
- `signapy.discover` for a binary target against categorical, continuous, and
|
|
46
|
+
ordinal features.
|
|
47
|
+
- Evidence to find, quantify, localize, and validate predictive signal; see
|
|
48
|
+
`docs/metrics.md` for interpretation and `docs/architecture.md` for design.
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
# Contributing to SignaPy
|
|
2
|
+
|
|
3
|
+
Thanks for your interest in SignaPy. It's a pre-1.0 library, so the API may
|
|
4
|
+
still change, and feedback at this stage is especially useful: bug reports,
|
|
5
|
+
questions about the statistics, and ideas are all welcome.
|
|
6
|
+
|
|
7
|
+
## Contact
|
|
8
|
+
|
|
9
|
+
For anything that doesn't fit a GitHub issue or pull request, email
|
|
10
|
+
**dev.meisel+signapy@gmail.com**.
|
|
11
|
+
|
|
12
|
+
- **Bugs and feature requests:**
|
|
13
|
+
[open an issue](https://github.com/Carmeisel101/signapy/issues). Include the
|
|
14
|
+
SignaPy version, your Python version, and a small example that reproduces
|
|
15
|
+
the problem (a few rows of synthetic data are ideal).
|
|
16
|
+
- **Larger changes:** please open an issue or email first, so we can agree on
|
|
17
|
+
the approach before you spend time on it.
|
|
18
|
+
- **Security concerns:** email rather than opening a public issue.
|
|
19
|
+
|
|
20
|
+
## Development setup
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
git clone https://github.com/Carmeisel101/signapy.git
|
|
24
|
+
cd signapy
|
|
25
|
+
python -m venv .venv
|
|
26
|
+
source .venv/bin/activate
|
|
27
|
+
python -m pip install -e ".[dev]"
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
The `dev` extra installs the test and lint tools and the optional `plot` and
|
|
31
|
+
`polars` dependencies. If you use [uv](https://docs.astral.sh/uv/), the
|
|
32
|
+
equivalent is `uv run --extra dev pytest`.
|
|
33
|
+
|
|
34
|
+
## Before you open a pull request
|
|
35
|
+
|
|
36
|
+
CI runs the same checks, on Python 3.10 through 3.14:
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
pytest
|
|
40
|
+
ruff check .
|
|
41
|
+
ruff format --check .
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
Run `ruff format .` to fix formatting. Warnings are errors in the test suite,
|
|
45
|
+
because silent numerical problems are unacceptable in a statistics library.
|
|
46
|
+
|
|
47
|
+
## Guidelines
|
|
48
|
+
|
|
49
|
+
- **Add tests** for new behavior and for bug fixes. Tests live in `tests/`.
|
|
50
|
+
- **Keep the docs in step with the code.** User-facing changes go in the
|
|
51
|
+
README, `docs/metrics.md` (what a statistic means and how to read it), or
|
|
52
|
+
`docs/architecture.md` (design and scope), and get an entry under
|
|
53
|
+
"Unreleased" in `CHANGELOG.md`.
|
|
54
|
+
- **Be honest about what the statistics show.** SignaPy reports associations
|
|
55
|
+
in the sample, not causes. Wording in docs, docstrings, and plot text should
|
|
56
|
+
not imply more than the numbers support.
|
|
57
|
+
- **Keep changes focused.** One concern per pull request is easier to review.
|
|
58
|
+
- **Match the surrounding code:** naming, comment density, and typing.
|
|
59
|
+
|
|
60
|
+
## License
|
|
61
|
+
|
|
62
|
+
By contributing, you agree that your contributions are licensed under the
|
|
63
|
+
project's [MIT License](LICENSE).
|
signapy-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Carlos Meisel
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|