adstk 0.0.1__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.
@@ -0,0 +1,22 @@
1
+ on:
2
+ push:
3
+ branches: [main]
4
+ pull_request:
5
+
6
+ jobs:
7
+ test:
8
+ runs-on: docker
9
+ steps:
10
+ - uses: actions/checkout@v4
11
+ - run: pip install ".[dev]"
12
+ - run: ruff check .
13
+ - run: mypy src/
14
+ - run: pytest
15
+
16
+ docs:
17
+ runs-on: docker
18
+ needs: test
19
+ steps:
20
+ - uses: actions/checkout@v4
21
+ - run: pip install ".[docs]"
22
+ - run: mkdocs build --strict
adstk-0.0.1/.gitignore ADDED
@@ -0,0 +1,236 @@
1
+ # ---> Python
2
+ # Byte-compiled / optimized / DLL files
3
+ __pycache__/
4
+ *.py[codz]
5
+ *$py.class
6
+
7
+ # C extensions
8
+ *.so
9
+
10
+ # Distribution / packaging
11
+ .Python
12
+ build/
13
+ develop-eggs/
14
+ dist/
15
+ downloads/
16
+ eggs/
17
+ .eggs/
18
+ lib/
19
+ lib64/
20
+ parts/
21
+ sdist/
22
+ var/
23
+ wheels/
24
+ share/python-wheels/
25
+ *.egg-info/
26
+ .installed.cfg
27
+ *.egg
28
+ MANIFEST
29
+
30
+ # PyInstaller
31
+ # Usually these files are written by a python script from a template
32
+ # before PyInstaller builds the exe, so as to inject date/other infos into it.
33
+ *.manifest
34
+ *.spec
35
+
36
+ # Installer logs
37
+ pip-log.txt
38
+ pip-delete-this-directory.txt
39
+
40
+ # Unit test / coverage reports
41
+ htmlcov/
42
+ .tox/
43
+ .nox/
44
+ .coverage
45
+ .coverage.*
46
+ .cache
47
+ nosetests.xml
48
+ coverage.xml
49
+ *.cover
50
+ *.py.cover
51
+ .hypothesis/
52
+ .pytest_cache/
53
+ cover/
54
+
55
+ # Translations
56
+ *.mo
57
+ *.pot
58
+
59
+ # Django stuff:
60
+ *.log
61
+ local_settings.py
62
+ db.sqlite3
63
+ db.sqlite3-journal
64
+
65
+ # Flask stuff:
66
+ instance/
67
+ .webassets-cache
68
+
69
+ # Scrapy stuff:
70
+ .scrapy
71
+
72
+ # Sphinx documentation
73
+ docs/_build/
74
+
75
+ # PyBuilder
76
+ .pybuilder/
77
+ target/
78
+
79
+ # Jupyter Notebook
80
+ .ipynb_checkpoints
81
+
82
+ # IPython
83
+ profile_default/
84
+ ipython_config.py
85
+
86
+ # pyenv
87
+ # For a library or package, you might want to ignore these files since the code is
88
+ # intended to run in multiple environments; otherwise, check them in:
89
+ # .python-version
90
+
91
+ # pipenv
92
+ # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
93
+ # However, in case of collaboration, if having platform-specific dependencies or dependencies
94
+ # having no cross-platform support, pipenv may install dependencies that don't work, or not
95
+ # install all needed dependencies.
96
+ # Pipfile.lock
97
+
98
+ # UV
99
+ # Similar to Pipfile.lock, it is generally recommended to include uv.lock in version control.
100
+ # This is especially recommended for binary packages to ensure reproducibility, and is more
101
+ # commonly ignored for libraries.
102
+ # uv.lock
103
+
104
+ # poetry
105
+ # Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
106
+ # This is especially recommended for binary packages to ensure reproducibility, and is more
107
+ # commonly ignored for libraries.
108
+ # https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
109
+ # poetry.lock
110
+ # poetry.toml
111
+
112
+ # pdm
113
+ # Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
114
+ # pdm recommends including project-wide configuration in pdm.toml, but excluding .pdm-python.
115
+ # https://pdm-project.org/en/latest/usage/project/#working-with-version-control
116
+ # pdm.lock
117
+ # pdm.toml
118
+ .pdm-python
119
+ .pdm-build/
120
+
121
+ # pixi
122
+ # Similar to Pipfile.lock, it is generally recommended to include pixi.lock in version control.
123
+ # pixi.lock
124
+ # Pixi creates a virtual environment in the .pixi directory, just like venv module creates one
125
+ # in the .venv directory. It is recommended not to include this directory in version control.
126
+ .pixi
127
+
128
+ # PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
129
+ __pypackages__/
130
+
131
+ # Celery stuff
132
+ celerybeat-schedule
133
+ celerybeat.pid
134
+
135
+ # Redis
136
+ *.rdb
137
+ *.aof
138
+ *.pid
139
+
140
+ # RabbitMQ
141
+ mnesia/
142
+ rabbitmq/
143
+ rabbitmq-data/
144
+
145
+ # ActiveMQ
146
+ activemq-data/
147
+
148
+ # SageMath parsed files
149
+ *.sage.py
150
+
151
+ # Environments
152
+ .env
153
+ .envrc
154
+ .venv
155
+ env/
156
+ venv/
157
+ ENV/
158
+ env.bak/
159
+ venv.bak/
160
+
161
+ # Spyder project settings
162
+ .spyderproject
163
+ .spyproject
164
+
165
+ # Rope project settings
166
+ .ropeproject
167
+
168
+ # mkdocs documentation
169
+ /site
170
+
171
+ # mypy
172
+ .mypy_cache/
173
+ .dmypy.json
174
+ dmypy.json
175
+
176
+ # Pyre type checker
177
+ .pyre/
178
+
179
+ # pytype static type analyzer
180
+ .pytype/
181
+
182
+ # Cython debug symbols
183
+ cython_debug/
184
+
185
+ # PyCharm
186
+ # JetBrains specific template is maintained in a separate JetBrains.gitignore that can
187
+ # be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
188
+ # and can be added to the global gitignore or merged into this file. For a more nuclear
189
+ # option (not recommended) you can uncomment the following to ignore the entire idea folder.
190
+ # .idea/
191
+
192
+ # Abstra
193
+ # Abstra is an AI-powered process automation framework.
194
+ # Ignore directories containing user credentials, local state, and settings.
195
+ # Learn more at https://abstra.io/docs
196
+ .abstra/
197
+
198
+ # Visual Studio Code
199
+ # Visual Studio Code specific template is maintained in a separate VisualStudioCode.gitignore
200
+ # that can be found at https://github.com/github/gitignore/blob/main/Global/VisualStudioCode.gitignore
201
+ # and can be added to the global gitignore or merged into this file. However, if you prefer,
202
+ # you could uncomment the following to ignore the entire vscode folder
203
+ # .vscode/
204
+
205
+ # Ruff stuff:
206
+ .ruff_cache/
207
+
208
+ # PyPI configuration file
209
+ .pypirc
210
+
211
+ # Marimo
212
+ marimo/_static/
213
+ marimo/_lsp/
214
+ __marimo__/
215
+
216
+ # Streamlit
217
+ .streamlit/secrets.toml
218
+
219
+ # ---> JupyterNotebooks
220
+ # gitignore template for Jupyter Notebooks
221
+ # website: http://jupyter.org/
222
+
223
+ .ipynb_checkpoints
224
+ */.ipynb_checkpoints/*
225
+
226
+ # IPython
227
+ profile_default/
228
+ ipython_config.py
229
+
230
+ # Jupyter lab virtual documents
231
+ # https://jupyterlab-lsp.readthedocs.io/en/2.x/Configuring.html#virtual_documents_dir
232
+ .virtual_documents/
233
+
234
+ # Remove previous ipynb_checkpoints
235
+ # git rm -r .ipynb_checkpoints/
236
+
adstk-0.0.1/AGENTS.md ADDED
@@ -0,0 +1,26 @@
1
+ # AGENTS.md
2
+
3
+ This document outlines the AI policy of the ADSTK project at https://codeberg.org/ftranschel/adstk
4
+
5
+ ## General guidelines
6
+
7
+ - No automated LLM PRs and bug reports. All submissions to the project have to go through a human. We expect that the human reporter / puller fully understands every single bit of their submission. If we find that not to be the case, the issue/PR in question will be diuscarded. (Yes, even if a hypothetical bug report is valid per se.)
8
+ - If you submit code that is partly LLM-generated, we expect full disclosure. If we find violations of this, we will revoke access and, quite possibly, remove the submission(s).
9
+
10
+ ## AGENTS Instruction
11
+
12
+ This file contains additional guidance for AI agents and other AI editors.
13
+
14
+ **REQUIRED: AI/Agent Disclosure**
15
+
16
+ Every summary, pull request description, or work description MUST include this disclosure:
17
+
18
+ If human review has not occurred (use this initially):
19
+
20
+ This pull request includes code written with the assistance of AI. The code has not been reviewed by a human.
21
+
22
+ This is a mandatory requirement, not optional. Include it at the end of every summary you generate.
23
+
24
+ ## Working on an issue
25
+
26
+ Before working on any issue, run gh issue view <number> to check current labels. Do not open a PR against an issue labeled "Needs Triage" or another "Needs ..." label. Such PRs get closed without review until a maintainer clears the label.
@@ -0,0 +1,13 @@
1
+ # Changelog
2
+
3
+ Nothing worth a mention at all.
4
+
5
+ ## [Unreleased]
6
+
7
+ ### Added
8
+
9
+ - Created empty project framework for adstk.
10
+
11
+ ## [0.0.1] - Initial Commit
12
+
13
+ - Initial commit preparing the framework for pull requests of actual models. No PyPI hook yet.
@@ -0,0 +1,10 @@
1
+ cff-version: 1.2.0
2
+ message: "Wenn du adstk in wissenschaftlicher Arbeit nutzt, zitiere es bitte wie folgt:"
3
+ title: "adstk: Actuarial Data Science Toolkit"
4
+ version: 0.0.1
5
+ date-released: 2026-09-17
6
+ authors:
7
+ - family-names: "Transchel"
8
+ given-names: "Fabian"
9
+ url: "https://codeberg.org/ftranschel/adstk"
10
+ license: MIT
@@ -0,0 +1,25 @@
1
+ # adstk code of conduct
2
+
3
+ The aim of this CoC: Maximal inclusivity for humans, clear guardrails for agents and LLM submissions. Zero tolerance for misconduct of any kind.
4
+
5
+ ## Expected conduct
6
+
7
+ - Be respectful and constructive in PRs, issues and all other interactions.
8
+ - Be constructive w.r.t. the code. No ad hominems.
9
+
10
+ ## Inacceptable conduct
11
+
12
+ - No insults and offenses.
13
+ - No discrimination.
14
+
15
+ ## AI policy
16
+
17
+ - No automated LLM PRs and bug reports. All submissions to the project have to go through a human. We expect that the human reporter / puller fully understands every single bit of their submission. If we find that not to be the case, the issue/PR in question will be diuscarded. (Yes, even if a hypothetical bug report is valid per se.)
18
+ - If you submit code that is partly LLM-generated, we expect full disclosure. If we find violations of this, we will revoke access and, quite possibly, remove the submission(s).
19
+
20
+ ## Violations to this CoC
21
+
22
+ Infractions are to be pointed at ftranschel@hs-harz.de.
23
+ Dealings are confidential unless otherwise required.
24
+
25
+ The codex is based on [Contributor Covenant](https://www.contributor-covenant.org/). All changes are our own interpretation of the aims and guidelines formulated therein.
@@ -0,0 +1,60 @@
1
+ # Contributing to adstk
2
+
3
+ We appreciate submissions to adstk as long as they allow progress for both the actuarial profession as well as the package scope and health.
4
+
5
+ Here's how to help:
6
+
7
+ ## Setup
8
+
9
+ ```bash
10
+ git clone https://codeberg.org/ftranschel/adstk.git
11
+ cd adstk
12
+ python -m venv .venv
13
+ source .venv/bin/activate # Windows: .venv\Scripts\activate
14
+ pip install -e ".[dev,docs]"
15
+ ```
16
+
17
+ ## Tests & Lint lokal ausführen
18
+
19
+ ```bash
20
+ pytest
21
+ ruff check .
22
+ mypy src/
23
+ ```
24
+
25
+ ## Contributing a new model
26
+
27
+ 1. Open an issue using the "Model request" template (or pick up an
28
+ existing one), including a professional reference (paper, textbook, standard).
29
+ 2. Create a new submodule under `src/adstk/<area>/` (e.g.
30
+ `src/adstk/explain/`, `src/adstk/telematics/` - depending on the topic area).
31
+ 3. Use NumPy-style docstrings (including the formula, parameters, returns,
32
+ examples) - this automatically generates the API documentation.
33
+ 4. Add tests under `tests/`, in particular numerical reference values
34
+ checked against an independent source (textbook, R package, etc.).
35
+ 5. Open a pull request. Note: any LLM involvement in your submission must
36
+ be fully disclosed - see [AGENTS.md](AGENTS.md).
37
+
38
+ ## Docstring style (NumPy format)
39
+
40
+ ```python
41
+ def example(x: float, a: float) -> float:
42
+ """Short description.
43
+
44
+ Parameters
45
+ ----------
46
+ x : float
47
+ Description.
48
+ a : float
49
+ Description.
50
+
51
+ Returns
52
+ -------
53
+ float
54
+ Description.
55
+ """
56
+ ```
57
+
58
+ ## Verhaltenskodex
59
+
60
+ Please follow our [Code of Conduct](CODE_OF_CONDUCT.md).
adstk-0.0.1/LICENSE ADDED
@@ -0,0 +1,18 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 ftranschel
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
6
+ associated documentation files (the "Software"), to deal in the Software without restriction, including
7
+ without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the
9
+ following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be included in all copies or substantial
12
+ portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
15
+ LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO
16
+ EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
17
+ IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
18
+ USE OR OTHER DEALINGS IN THE SOFTWARE.
adstk-0.0.1/PKG-INFO ADDED
@@ -0,0 +1,107 @@
1
+ Metadata-Version: 2.5
2
+ Name: adstk
3
+ Version: 0.0.1
4
+ Summary: ADSTK aims to bundle together relevant actuarial models, tools and code simplifications to enrich the Actuarial / Insurance Data Science experience in the Python ecosystem.
5
+ Project-URL: Homepage, https://codeberg.org/ftranschel/adstk
6
+ Project-URL: Repository, https://codeberg.org/ftranschel/adstk
7
+ Project-URL: Issues, https://codeberg.org/ftranschel/adstk/issues
8
+ Project-URL: Documentation, https://ftranschel.codeberg.page/adstk/
9
+ Author-email: Fabian Transchel <ftranschel@hs-harz.de>
10
+ License-Expression: MIT
11
+ License-File: LICENSE
12
+ Keywords: actuarial,aktuariat,data science,inspection,insurance,pricing,telematics
13
+ Classifier: Development Status :: 2 - Pre-Alpha
14
+ Classifier: Intended Audience :: Science/Research
15
+ Classifier: License :: OSI Approved :: MIT License
16
+ Classifier: Programming Language :: Python :: 3
17
+ Classifier: Programming Language :: Python :: 3.10
18
+ Classifier: Programming Language :: Python :: 3.11
19
+ Classifier: Programming Language :: Python :: 3.12
20
+ Classifier: Topic :: Office/Business :: Financial
21
+ Classifier: Topic :: Scientific/Engineering :: Mathematics
22
+ Classifier: Typing :: Typed
23
+ Requires-Python: >=3.10
24
+ Requires-Dist: numpy>=1.24
25
+ Requires-Dist: pandas>=1.5
26
+ Requires-Dist: scipy>=1.10
27
+ Provides-Extra: docs
28
+ Requires-Dist: mkdocs-material>=9.5; extra == 'docs'
29
+ Requires-Dist: mkdocstrings[python]>=0.25; extra == 'docs'
30
+ Provides-Extra: test
31
+ Requires-Dist: matplotlib; extra == 'test'
32
+ Requires-Dist: pytest; extra == 'test'
33
+ Requires-Dist: pytest-cov; extra == 'test'
34
+ Requires-Dist: scikit-learn; extra == 'test'
35
+ Description-Content-Type: text/markdown
36
+
37
+ # adstk
38
+
39
+ ADSTK aims to bundle together relevant actuarial models, tools and code simplifications to enrich the Actuarial / Insurance Data Science experience in the Python ecosystem.
40
+ ---
41
+
42
+ ## Features
43
+
44
+ ADSTK currently ships with a limited number of methods and use cases:
45
+
46
+ * Partial dependence display with support for individual conditional expectation curves (ICE)
47
+
48
+ ### Dependencies
49
+
50
+ adstk requires:
51
+
52
+ - Python (>= 3.10)
53
+ - NumPy (>= 1.24)
54
+ - SciPy (>= 1.10)
55
+
56
+ Optional requirements for plotting etc.
57
+
58
+ - matplotlib ()
59
+ - plotly ()
60
+
61
+ ### User installation
62
+
63
+ The easiest way to install adstk will using `pip` once we publish on PyPi:
64
+
65
+ pip install -U adstk
66
+
67
+ ## Changelog
68
+
69
+ See the [changelog](CHANGELOG.md) for a history of notable changes to adstk.
70
+
71
+ ## Development
72
+
73
+ We welcome human contributors of all experience levels. The adstk community
74
+ goals are to be helpful, welcoming, and effective. The
75
+ [Contributing guide](CONTRIBUTING.md) has detailed information about
76
+ contributing code, documentation, tests, and more. Please also note our
77
+ [AI contribution policy](AGENTS.md) before submitting anything.
78
+
79
+ ### Important links
80
+
81
+ - Official source code repo: https://codeberg.org/ftranschel/adstk
82
+ - Download releases: https://pypi.org/project/adstk/
83
+ - Issue tracker: https://codeberg.org/ftranschel/adstk/issues
84
+
85
+ ### Source code
86
+
87
+ You can check the latest sources with the command:
88
+
89
+ git clone https://codeberg.org/ftranschel/adstk.git
90
+
91
+ ### Contributing
92
+
93
+ To learn more about making a contribution to adstk, please see our
94
+ [Contributing guide](CONTRIBUTING.md).
95
+
96
+ ### Testing
97
+
98
+ After installation, you can launch the test suite from the source
99
+ directory (you will need `pytest` installed):
100
+
101
+ pytest
102
+
103
+ ### Submitting a Pull Request
104
+
105
+ Before opening a pull request, please read the
106
+ [Contributing guide](CONTRIBUTING.md) and our [AI policy](AGENTS.md) to
107
+ make sure your submission complies with our guidelines.
adstk-0.0.1/README.md ADDED
@@ -0,0 +1,71 @@
1
+ # adstk
2
+
3
+ ADSTK aims to bundle together relevant actuarial models, tools and code simplifications to enrich the Actuarial / Insurance Data Science experience in the Python ecosystem.
4
+ ---
5
+
6
+ ## Features
7
+
8
+ ADSTK currently ships with a limited number of methods and use cases:
9
+
10
+ * Partial dependence display with support for individual conditional expectation curves (ICE)
11
+
12
+ ### Dependencies
13
+
14
+ adstk requires:
15
+
16
+ - Python (>= 3.10)
17
+ - NumPy (>= 1.24)
18
+ - SciPy (>= 1.10)
19
+
20
+ Optional requirements for plotting etc.
21
+
22
+ - matplotlib ()
23
+ - plotly ()
24
+
25
+ ### User installation
26
+
27
+ The easiest way to install adstk will using `pip` once we publish on PyPi:
28
+
29
+ pip install -U adstk
30
+
31
+ ## Changelog
32
+
33
+ See the [changelog](CHANGELOG.md) for a history of notable changes to adstk.
34
+
35
+ ## Development
36
+
37
+ We welcome human contributors of all experience levels. The adstk community
38
+ goals are to be helpful, welcoming, and effective. The
39
+ [Contributing guide](CONTRIBUTING.md) has detailed information about
40
+ contributing code, documentation, tests, and more. Please also note our
41
+ [AI contribution policy](AGENTS.md) before submitting anything.
42
+
43
+ ### Important links
44
+
45
+ - Official source code repo: https://codeberg.org/ftranschel/adstk
46
+ - Download releases: https://pypi.org/project/adstk/
47
+ - Issue tracker: https://codeberg.org/ftranschel/adstk/issues
48
+
49
+ ### Source code
50
+
51
+ You can check the latest sources with the command:
52
+
53
+ git clone https://codeberg.org/ftranschel/adstk.git
54
+
55
+ ### Contributing
56
+
57
+ To learn more about making a contribution to adstk, please see our
58
+ [Contributing guide](CONTRIBUTING.md).
59
+
60
+ ### Testing
61
+
62
+ After installation, you can launch the test suite from the source
63
+ directory (you will need `pytest` installed):
64
+
65
+ pytest
66
+
67
+ ### Submitting a Pull Request
68
+
69
+ Before opening a pull request, please read the
70
+ [Contributing guide](CONTRIBUTING.md) and our [AI policy](AGENTS.md) to
71
+ make sure your submission complies with our guidelines.
@@ -0,0 +1,13 @@
1
+ # adstk
2
+
3
+ Aktuarielle Modelle für Python - Bausteine, die im Python-Ökosystem
4
+ bislang fehlen oder nur unvollständig implementiert sind.
5
+
6
+ ## Erste Schritte
7
+
8
+ ```bash
9
+ pip install adstk
10
+ ```
11
+
12
+ Die API-Referenz wird automatisch aus den Docstrings im Quellcode
13
+ generiert (siehe `docs/api/`), sobald erste Module implementiert sind.
@@ -0,0 +1,3 @@
1
+ # Beispiele
2
+
3
+ Hier folgen ausführlichere Beispiele/Notebooks zur Nutzung von adstk.
@@ -0,0 +1,69 @@
1
+ """
2
+ ICE curves for model inspection
3
+ ================================
4
+
5
+ This example shows how to compute and plot Individual Conditional
6
+ Expectation (ICE) curves with :func:`adstk.inspect.create_ice_curves`
7
+ and :func:`adstk.inspect.plot_ice_curves`.
8
+
9
+ ICE curves show how a fitted model's prediction for a *single*
10
+ instance changes as one feature is varied while every other feature is
11
+ held fixed. Averaging ICE curves across instances recovers the
12
+ Partial Dependence Plot (PDP).
13
+ """
14
+
15
+ # %%
16
+ # Fit a model on synthetic data
17
+ # ------------------------------
18
+ # We use a small toy marketing-mix-style dataset: spend on two
19
+ # channels and a price, predicting some outcome.
20
+
21
+ import numpy as np
22
+ import pandas as pd
23
+ from sklearn.ensemble import RandomForestRegressor
24
+
25
+ from adstk.inspect import create_ice_curves, plot_ice_curves
26
+
27
+ rng = np.random.default_rng(0)
28
+ n_samples = 200
29
+ X = pd.DataFrame(
30
+ {
31
+ "tv_spend": rng.uniform(0, 100, n_samples),
32
+ "social_spend": rng.uniform(0, 50, n_samples),
33
+ "price": rng.uniform(10, 30, n_samples),
34
+ }
35
+ )
36
+ y = (
37
+ 0.8 * X["tv_spend"]
38
+ + 1.2 * X["social_spend"]
39
+ - 2.0 * X["price"]
40
+ + rng.normal(0, 5, n_samples)
41
+ )
42
+
43
+ model = RandomForestRegressor(n_estimators=100, random_state=0).fit(X, y)
44
+
45
+ # %%
46
+ # Compute raw ICE curve data for a single feature
47
+ # -------------------------------------------------
48
+ # ``create_ice_curves`` returns the grid of swept feature values and a
49
+ # ``(n_instances, n_points)`` array of predictions -- one row per
50
+ # instance, one column per grid point.
51
+
52
+ sample = X.sample(30, random_state=0)
53
+ feature_values, ice_curves = create_ice_curves(model, sample, "tv_spend")
54
+ print(f"feature_values shape: {feature_values.shape}")
55
+ print(f"ice_curves shape: {ice_curves.shape}")
56
+
57
+ # %%
58
+ # Plot ICE curves and the PDP for several features
59
+ # ---------------------------------------------------
60
+ # ``plot_ice_curves`` computes ICE curves for each feature in
61
+ # ``feature_list`` and plots a sample of the individual curves in blue
62
+ # alongside the averaged PDP in red.
63
+
64
+ fig, axes = plot_ice_curves(
65
+ model,
66
+ sample,
67
+ feature_list=["tv_spend", "social_spend", "price"],
68
+ random_state=0,
69
+ )
adstk-0.0.1/mkdocs.yml ADDED
@@ -0,0 +1,35 @@
1
+ site_name: adstk
2
+ site_description: Actuarial Data Science Toolkit
3
+ repo_url: https://codeberg.org/ftranschel/adstk
4
+ docs_dir: docs
5
+
6
+ theme:
7
+ name: material
8
+ features:
9
+ - navigation.sections
10
+ - content.code.copy
11
+
12
+ plugins:
13
+ - search
14
+ - mkdocstrings:
15
+ handlers:
16
+ python:
17
+ options:
18
+ docstring_style: numpy
19
+ show_source: true
20
+ show_root_heading: true
21
+
22
+ markdown_extensions:
23
+ - pymdownx.arithmatex:
24
+ generic: true
25
+ - admonition
26
+ - pymdownx.details
27
+ - pymdownx.superfences
28
+
29
+ extra_javascript:
30
+ - https://cdnjs.cloudflare.com/ajax/libs/mathjax/3.2.2/es5/tex-mml-chtml.min.js
31
+
32
+ nav:
33
+ - Start: index.md
34
+ # API-Referenz: Seiten unter docs/api/ ergänzen, sobald erste Module existieren.
35
+ # Beispiel: "::: paket.modul.funktion" in eine .md-Datei, siehe mkdocstrings-Doku.
@@ -0,0 +1,71 @@
1
+ [build-system]
2
+ requires = ["hatchling"]
3
+ build-backend = "hatchling.build"
4
+
5
+ [project]
6
+ name = "adstk"
7
+ version = "0.0.1"
8
+ description = "ADSTK aims to bundle together relevant actuarial models, tools and code simplifications to enrich the Actuarial / Insurance Data Science experience in the Python ecosystem."
9
+ readme = "README.md"
10
+ license = "MIT"
11
+ requires-python = ">=3.10"
12
+ authors = [
13
+ { name = "Fabian Transchel", email = "ftranschel@hs-harz.de" },
14
+ ]
15
+ keywords = ["actuarial", "aktuariat", "pricing", "insurance","inspection","telematics","data science"]
16
+ classifiers = [
17
+ "Development Status :: 2 - Pre-Alpha",
18
+ "Intended Audience :: Science/Research",
19
+ "License :: OSI Approved :: MIT License",
20
+ "Programming Language :: Python :: 3",
21
+ "Programming Language :: Python :: 3.10",
22
+ "Programming Language :: Python :: 3.11",
23
+ "Programming Language :: Python :: 3.12",
24
+ "Topic :: Office/Business :: Financial",
25
+ "Topic :: Scientific/Engineering :: Mathematics",
26
+ "Typing :: Typed",
27
+ ]
28
+
29
+ dependencies = [
30
+ "numpy>=1.24",
31
+ "scipy>=1.10",
32
+ "pandas>=1.5", # add this: adstk.inspect needs DataFrame input
33
+ ]
34
+
35
+ [project.optional-dependencies]
36
+ test = [
37
+ "pytest",
38
+ "pytest-cov",
39
+ "matplotlib",
40
+ "scikit-learn",
41
+ ]
42
+
43
+ docs = [
44
+ "mkdocs-material>=9.5",
45
+ "mkdocstrings[python]>=0.25",
46
+ ]
47
+
48
+ [project.urls]
49
+ Homepage = "https://codeberg.org/ftranschel/adstk"
50
+ Repository = "https://codeberg.org/ftranschel/adstk"
51
+ Issues = "https://codeberg.org/ftranschel/adstk/issues"
52
+ Documentation = "https://ftranschel.codeberg.page/adstk/"
53
+
54
+ [tool.hatch.build.targets.wheel]
55
+ packages = ["src/adstk"]
56
+
57
+ [tool.ruff]
58
+ line-length = 100
59
+ target-version = "py310"
60
+
61
+ [tool.ruff.lint]
62
+ select = ["E", "F", "I", "UP", "B", "SIM"]
63
+
64
+ [tool.mypy]
65
+ python_version = "3.10"
66
+ strict = true
67
+ packages = ["adstk"]
68
+
69
+ [tool.pytest.ini_options]
70
+ testpaths = ["tests"]
71
+ addopts = "--cov=adstk --cov-report=term-missing"
@@ -0,0 +1,10 @@
1
+ """adstk - Actuarial Data Science Toolkit (for Python)
2
+
3
+ ADSTK aims to bundle together relevant actuarial models, tools and code simplifications to enrich the insurance Data Science experience in the Python ecosystem.
4
+ """
5
+
6
+ from __future__ import annotations
7
+
8
+ __version__ = "0.1.0"
9
+
10
+ __all__ = ["__version__"]
@@ -0,0 +1,8 @@
1
+ """adstk.inspect: model inspection utilities."""
2
+
3
+ from .ice import create_ice_curves, plot_ice_curves
4
+
5
+ __all__ = [
6
+ "create_ice_curves",
7
+ "plot_ice_curves"
8
+ ]
@@ -0,0 +1,164 @@
1
+ """Individual Conditional Expectation (ICE) curves.
2
+
3
+ Individual Conditional Expectation (ICE) curves show how a fitted model's
4
+ prediction for a single instance changes as one feature is varied while
5
+ all other features are held fixed. Averaging ICE curves across instances
6
+ recovers the Partial Dependence Plot (PDP).
7
+
8
+ Part of ``adstk.inspect``. Public API:
9
+
10
+ - :func:`create_ice_curves` computes the raw ICE curve data.
11
+ - :func:`plot_ice_curves` computes ICE curves for one or more features
12
+ and renders them, overlaying the PDP.
13
+ """
14
+
15
+ from __future__ import annotations
16
+
17
+ from typing import Optional, Sequence, Tuple
18
+
19
+ import numpy as np
20
+ import pandas as pd
21
+
22
+
23
+ def create_ice_curves(
24
+ model,
25
+ X: pd.DataFrame,
26
+ feature_name: str,
27
+ n_points: int = 50,
28
+ feature_range: Optional[Tuple[float, float]] = None,
29
+ ) -> Tuple[np.ndarray, np.ndarray]:
30
+ """Compute Individual Conditional Expectation (ICE) curves.
31
+
32
+ For every row in ``X``, ``feature_name`` is swept across ``n_points``
33
+ values spanning ``feature_range`` (or the observed min/max) while all
34
+ other feature values are held at their originally observed values,
35
+ and the model's prediction is recorded at each point.
36
+
37
+ Parameters
38
+ ----------
39
+ model : object
40
+ A fitted estimator exposing ``predict(X: np.ndarray) -> np.ndarray``.
41
+ X : pandas.DataFrame
42
+ Instances to compute curves for, with columns in the same order
43
+ the model expects.
44
+ feature_name : str
45
+ Column of ``X`` to vary.
46
+ n_points : int, default=50
47
+ Number of grid points to evaluate the feature at.
48
+ feature_range : tuple(float, float), optional
49
+ ``(min, max)`` to sweep over. Defaults to the observed range of
50
+ ``feature_name`` in ``X``.
51
+
52
+ Returns
53
+ -------
54
+ feature_values : numpy.ndarray, shape (n_points,)
55
+ The grid ``feature_name`` was evaluated at.
56
+ ice_curves : numpy.ndarray, shape (len(X), n_points)
57
+ ``ice_curves[i, j]`` is the prediction for row ``i`` of ``X``
58
+ with ``feature_name`` fixed at ``feature_values[j]``.
59
+
60
+ Raises
61
+ ------
62
+ KeyError
63
+ If ``feature_name`` is not a column of ``X``.
64
+ ValueError
65
+ If ``X`` has no rows, or ``feature_range`` is decreasing.
66
+ """
67
+ if feature_name not in X.columns:
68
+ raise KeyError(
69
+ f"'{feature_name}' is not a column of X. "
70
+ f"Available columns: {list(X.columns)}"
71
+ )
72
+ if len(X) == 0:
73
+ raise ValueError("X must contain at least one row.")
74
+
75
+ if feature_range is None:
76
+ feature_min = X[feature_name].min()
77
+ feature_max = X[feature_name].max()
78
+ else:
79
+ feature_min, feature_max = feature_range
80
+ if feature_min > feature_max:
81
+ raise ValueError(
82
+ f"feature_range must not be decreasing, got ({feature_min}, {feature_max})."
83
+ )
84
+
85
+ feature_values = np.linspace(feature_min, feature_max, n_points)
86
+
87
+ n_samples = len(X)
88
+ feature_idx = X.columns.get_loc(feature_name)
89
+
90
+ # Build a single batch of (n_samples * n_points) modified rows so
91
+ # predict() is called once instead of n_samples * n_points times.
92
+ # This is the main cost driver for ICE curves at any real n_points.
93
+ batch = np.repeat(X.to_numpy(), n_points, axis=0)
94
+ batch[:, feature_idx] = np.tile(feature_values, n_samples)
95
+
96
+ predictions = np.asarray(model.predict(batch)).reshape(n_samples, n_points)
97
+
98
+ return feature_values, predictions
99
+
100
+
101
+ def plot_ice_curves(
102
+ model,
103
+ X: pd.DataFrame,
104
+ feature_list: Sequence[str],
105
+ n_points: int = 50,
106
+ n_ice_lines: int = 25,
107
+ random_state: Optional[int] = None,
108
+ ):
109
+ """Plot ICE curves (with overlaid PDP) for one or more features.
110
+
111
+ Parameters
112
+ ----------
113
+ model : object
114
+ A fitted estimator exposing ``predict``.
115
+ X : pandas.DataFrame
116
+ Instances to compute curves for. Pass a sample rather than the
117
+ full dataset -- cost scales with ``len(X) * n_points``.
118
+ feature_list : sequence of str
119
+ Feature columns to plot, one subplot each.
120
+ n_points : int, default=50
121
+ Grid resolution per feature.
122
+ n_ice_lines : int, default=25
123
+ Number of individual ICE curves to draw per subplot (drawing
124
+ all of ``len(X)`` gets unreadable fast).
125
+ random_state : int, optional
126
+ Seed controlling which instances are sampled for display.
127
+
128
+ Returns
129
+ -------
130
+ fig : matplotlib.figure.Figure
131
+ axes : numpy.ndarray of matplotlib.axes.Axes
132
+ """
133
+ try:
134
+ import matplotlib.pyplot as plt
135
+ except ImportError as exc: # pragma: no cover
136
+ raise ImportError(
137
+ "plot_ice_curves requires matplotlib. Install it with "
138
+ "`pip install matplotlib`."
139
+ ) from exc
140
+
141
+ rng = np.random.default_rng(random_state)
142
+
143
+ fig, axes = plt.subplots(1, len(feature_list), figsize=(5 * len(feature_list), 4))
144
+ axes = np.atleast_1d(axes)
145
+
146
+ for ax, feature in zip(axes, feature_list):
147
+ feature_vals, ice_data = create_ice_curves(model, X, feature, n_points)
148
+
149
+ n_lines = min(n_ice_lines, len(ice_data))
150
+ sample_indices = rng.choice(len(ice_data), n_lines, replace=False)
151
+ for idx in sample_indices:
152
+ ax.plot(feature_vals, ice_data[idx], alpha=0.4, color="tab:blue", linewidth=1)
153
+
154
+ pdp = np.mean(ice_data, axis=0)
155
+ ax.plot(feature_vals, pdp, color="tab:red", linewidth=2, label="PDP")
156
+
157
+ ax.set_xlabel(feature)
158
+ ax.set_ylabel("Prediction")
159
+ ax.set_title(f"ICE: {feature}")
160
+ ax.grid(True, alpha=0.3)
161
+ ax.legend()
162
+
163
+ fig.tight_layout()
164
+ return fig, axes
File without changes
File without changes
@@ -0,0 +1,81 @@
1
+ """Tests for adstk.inspect.ice."""
2
+
3
+ import numpy as np
4
+ import pandas as pd
5
+ import pytest
6
+
7
+ from adstk.inspect.ice import create_ice_curves, plot_ice_curves
8
+
9
+
10
+ class _LinearStub:
11
+ """Deterministic stand-in for a fitted model: predict = row sum."""
12
+
13
+ def predict(self, X):
14
+ return X.sum(axis=1)
15
+
16
+
17
+ @pytest.fixture
18
+ def sample_data():
19
+ return pd.DataFrame(
20
+ {
21
+ "a": [0.0, 1.0, 2.0],
22
+ "b": [10.0, 10.0, 10.0],
23
+ }
24
+ )
25
+
26
+
27
+ def test_create_ice_curves_shape(sample_data):
28
+ feature_values, ice_curves = create_ice_curves(_LinearStub(), sample_data, "a", n_points=5)
29
+ assert feature_values.shape == (5,)
30
+ assert ice_curves.shape == (len(sample_data), 5)
31
+
32
+
33
+ def test_create_ice_curves_default_range_matches_data(sample_data):
34
+ feature_values, _ = create_ice_curves(_LinearStub(), sample_data, "a", n_points=5)
35
+ assert feature_values[0] == pytest.approx(sample_data["a"].min())
36
+ assert feature_values[-1] == pytest.approx(sample_data["a"].max())
37
+
38
+
39
+ def test_create_ice_curves_explicit_range(sample_data):
40
+ feature_values, _ = create_ice_curves(
41
+ _LinearStub(), sample_data, "a", n_points=5, feature_range=(-5, 5)
42
+ )
43
+ assert feature_values[0] == pytest.approx(-5)
44
+ assert feature_values[-1] == pytest.approx(5)
45
+
46
+
47
+ def test_create_ice_curves_values_correct(sample_data):
48
+ # predict = a + b, and b is fixed at 10 for every row here, so each
49
+ # ICE curve should equal 10 + the swept 'a' grid exactly, regardless
50
+ # of that row's original 'a' value.
51
+ feature_values, ice_curves = create_ice_curves(_LinearStub(), sample_data, "a", n_points=5)
52
+ expected = 10.0 + feature_values
53
+ for row in ice_curves:
54
+ np.testing.assert_allclose(row, expected)
55
+
56
+
57
+ def test_create_ice_curves_missing_feature_raises(sample_data):
58
+ with pytest.raises(KeyError):
59
+ create_ice_curves(_LinearStub(), sample_data, "does_not_exist")
60
+
61
+
62
+ def test_create_ice_curves_empty_X_raises(sample_data):
63
+ with pytest.raises(ValueError):
64
+ create_ice_curves(_LinearStub(), sample_data.iloc[0:0], "a")
65
+
66
+
67
+ def test_create_ice_curves_invalid_range_raises(sample_data):
68
+ with pytest.raises(ValueError):
69
+ create_ice_curves(_LinearStub(), sample_data, "a", feature_range=(5, -5))
70
+
71
+
72
+ def test_plot_ice_curves_returns_figure_and_axes(sample_data):
73
+ matplotlib = pytest.importorskip("matplotlib")
74
+ matplotlib.use("Agg") # headless backend for CI
75
+
76
+ fig, axes = plot_ice_curves(
77
+ _LinearStub(), sample_data, feature_list=["a", "b"], n_points=5, random_state=0
78
+ )
79
+ assert len(axes) == 2
80
+ for ax in axes:
81
+ assert len(ax.lines) >= 1 # at least the PDP line was drawn