tusk-ml 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.
- tusk_ml-0.1.0/PKG-INFO +87 -0
- tusk_ml-0.1.0/README.md +77 -0
- tusk_ml-0.1.0/pyproject.toml +99 -0
- tusk_ml-0.1.0/pyproject.toml.orig +93 -0
- tusk_ml-0.1.0/src/tusk/__init__.py +21 -0
- tusk_ml-0.1.0/src/tusk/api.py +125 -0
- tusk_ml-0.1.0/src/tusk/compiler.py +371 -0
- tusk_ml-0.1.0/src/tusk/database.py +360 -0
- tusk_ml-0.1.0/src/tusk/dtypes.py +59 -0
- tusk_ml-0.1.0/src/tusk/exceptions.py +89 -0
- tusk_ml-0.1.0/src/tusk/feature_list.py +130 -0
- tusk_ml-0.1.0/src/tusk/features.py +357 -0
- tusk_ml-0.1.0/src/tusk/primitives/__init__.py +79 -0
- tusk_ml-0.1.0/src/tusk/primitives/aggregation.py +271 -0
- tusk_ml-0.1.0/src/tusk/primitives/base.py +161 -0
- tusk_ml-0.1.0/src/tusk/primitives/registry.py +96 -0
- tusk_ml-0.1.0/src/tusk/primitives/transform.py +400 -0
- tusk_ml-0.1.0/src/tusk/sklearn/__init__.py +17 -0
- tusk_ml-0.1.0/src/tusk/sklearn/_encoders.py +184 -0
- tusk_ml-0.1.0/src/tusk/sklearn/_frames.py +176 -0
- tusk_ml-0.1.0/src/tusk/sklearn/_lineage.py +102 -0
- tusk_ml-0.1.0/src/tusk/sklearn/transformers.py +453 -0
- tusk_ml-0.1.0/src/tusk/synthesis.py +480 -0
- tusk_ml-0.1.0/src/tusk/validation.py +421 -0
tusk_ml-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
Metadata-Version: 2.3
|
|
2
|
+
Name: tusk-ml
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Deep feature synthesis for narwhals dataframes
|
|
5
|
+
Requires-Dist: narwhals>=2.24
|
|
6
|
+
Requires-Dist: scikit-learn>=1.4 ; extra == 'sklearn'
|
|
7
|
+
Requires-Python: >=3.10
|
|
8
|
+
Provides-Extra: sklearn
|
|
9
|
+
Description-Content-Type: text/markdown
|
|
10
|
+
|
|
11
|
+
# tusk
|
|
12
|
+
|
|
13
|
+
In nature, narwhals use their tusk to find mates.
|
|
14
|
+
|
|
15
|
+
In data science, you can use tusk to connect [narwhals](https://narwhals-dev.github.io/narwhals/) dataframes.
|
|
16
|
+
|
|
17
|
+
This package implements deep feature synthesis to automate feature engineering with the power of your favorite dataframe library.
|
|
18
|
+
Powered by [narwhals](https://narwhals-dev.github.io/narwhals/), inspired by [featuretools](https://featuretools.alteryx.com/).
|
|
19
|
+
|
|
20
|
+
## Install
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
uv add tusk-ml
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
## Usage
|
|
27
|
+
|
|
28
|
+
```python
|
|
29
|
+
from datetime import datetime
|
|
30
|
+
|
|
31
|
+
import tusk
|
|
32
|
+
from tusk.primitives import Quantiles
|
|
33
|
+
|
|
34
|
+
db = tusk.Database("retail")
|
|
35
|
+
db.add_table("customers", customers_lf, primary_key="id", row_creation_time="signed_up_at")
|
|
36
|
+
db.add_table("sessions", sessions_lf, primary_key="id", row_creation_time="started_at")
|
|
37
|
+
db.add_table("transactions", tx_lf, primary_key="id", row_creation_time="occurred_at")
|
|
38
|
+
|
|
39
|
+
db.add_relationship(parent="customers", child="sessions", foreign_key="customer_id")
|
|
40
|
+
db.add_relationship(parent="sessions", child="transactions", foreign_key="session_id")
|
|
41
|
+
|
|
42
|
+
db.validate() # optional: confirm the keys really are keys, before you trust the numbers
|
|
43
|
+
|
|
44
|
+
feature_matrix, features = tusk.deep_feature_synthesis(
|
|
45
|
+
database=db,
|
|
46
|
+
target_table="customers",
|
|
47
|
+
agg_primitives=["mean", "count", Quantiles(qs=(0.25, 0.5, 0.75))],
|
|
48
|
+
trans_primitives=["month", "weekday"],
|
|
49
|
+
max_depth=2,
|
|
50
|
+
cutoff_time=datetime(2026, 1, 1),
|
|
51
|
+
)
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
`feature_matrix` comes back as an uncomputed query plan — tusk never collects —
|
|
55
|
+
so on a backend with a lazy frame type you get one back and decide when to
|
|
56
|
+
compute:
|
|
57
|
+
|
|
58
|
+
```python
|
|
59
|
+
matrix = feature_matrix.collect()
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
`features` is a `FeatureList` — a sequence of inspectable definitions that
|
|
63
|
+
knows its target table and can re-apply itself to new data:
|
|
64
|
+
|
|
65
|
+
```python
|
|
66
|
+
matrix = features.apply(db_new)
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
## Documentation
|
|
70
|
+
|
|
71
|
+
Full documentation lives in [`docs/`](docs/index.md):
|
|
72
|
+
|
|
73
|
+
- [Databases](docs/guide/databases.md) — tables, keys, relationships, and
|
|
74
|
+
[validating](docs/guide/databases.md#validation) them against the data.
|
|
75
|
+
- [Running DFS](docs/guide/deep-feature-synthesis.md) — depth, cutoff times, and the column naming scheme.
|
|
76
|
+
- [Primitives](docs/guide/primitives.md) — what ships with tusk and how it behaves.
|
|
77
|
+
- [Custom primitives](docs/guide/custom-primitives.md) — the extension point.
|
|
78
|
+
- [scikit-learn pipelines](docs/guide/sklearn.md) — DFS as a pipeline step, and
|
|
79
|
+
computing only the features you keep.
|
|
80
|
+
- [Differences from featuretools](docs/guide/featuretools.md) — if you are porting.
|
|
81
|
+
- [API reference](docs/api/index.md) — every public symbol.
|
|
82
|
+
|
|
83
|
+
Build the site locally with:
|
|
84
|
+
|
|
85
|
+
```bash
|
|
86
|
+
uv run --group docs zensical serve
|
|
87
|
+
```
|
tusk_ml-0.1.0/README.md
ADDED
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
# tusk
|
|
2
|
+
|
|
3
|
+
In nature, narwhals use their tusk to find mates.
|
|
4
|
+
|
|
5
|
+
In data science, you can use tusk to connect [narwhals](https://narwhals-dev.github.io/narwhals/) dataframes.
|
|
6
|
+
|
|
7
|
+
This package implements deep feature synthesis to automate feature engineering with the power of your favorite dataframe library.
|
|
8
|
+
Powered by [narwhals](https://narwhals-dev.github.io/narwhals/), inspired by [featuretools](https://featuretools.alteryx.com/).
|
|
9
|
+
|
|
10
|
+
## Install
|
|
11
|
+
|
|
12
|
+
```bash
|
|
13
|
+
uv add tusk-ml
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
## Usage
|
|
17
|
+
|
|
18
|
+
```python
|
|
19
|
+
from datetime import datetime
|
|
20
|
+
|
|
21
|
+
import tusk
|
|
22
|
+
from tusk.primitives import Quantiles
|
|
23
|
+
|
|
24
|
+
db = tusk.Database("retail")
|
|
25
|
+
db.add_table("customers", customers_lf, primary_key="id", row_creation_time="signed_up_at")
|
|
26
|
+
db.add_table("sessions", sessions_lf, primary_key="id", row_creation_time="started_at")
|
|
27
|
+
db.add_table("transactions", tx_lf, primary_key="id", row_creation_time="occurred_at")
|
|
28
|
+
|
|
29
|
+
db.add_relationship(parent="customers", child="sessions", foreign_key="customer_id")
|
|
30
|
+
db.add_relationship(parent="sessions", child="transactions", foreign_key="session_id")
|
|
31
|
+
|
|
32
|
+
db.validate() # optional: confirm the keys really are keys, before you trust the numbers
|
|
33
|
+
|
|
34
|
+
feature_matrix, features = tusk.deep_feature_synthesis(
|
|
35
|
+
database=db,
|
|
36
|
+
target_table="customers",
|
|
37
|
+
agg_primitives=["mean", "count", Quantiles(qs=(0.25, 0.5, 0.75))],
|
|
38
|
+
trans_primitives=["month", "weekday"],
|
|
39
|
+
max_depth=2,
|
|
40
|
+
cutoff_time=datetime(2026, 1, 1),
|
|
41
|
+
)
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
`feature_matrix` comes back as an uncomputed query plan — tusk never collects —
|
|
45
|
+
so on a backend with a lazy frame type you get one back and decide when to
|
|
46
|
+
compute:
|
|
47
|
+
|
|
48
|
+
```python
|
|
49
|
+
matrix = feature_matrix.collect()
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
`features` is a `FeatureList` — a sequence of inspectable definitions that
|
|
53
|
+
knows its target table and can re-apply itself to new data:
|
|
54
|
+
|
|
55
|
+
```python
|
|
56
|
+
matrix = features.apply(db_new)
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
## Documentation
|
|
60
|
+
|
|
61
|
+
Full documentation lives in [`docs/`](docs/index.md):
|
|
62
|
+
|
|
63
|
+
- [Databases](docs/guide/databases.md) — tables, keys, relationships, and
|
|
64
|
+
[validating](docs/guide/databases.md#validation) them against the data.
|
|
65
|
+
- [Running DFS](docs/guide/deep-feature-synthesis.md) — depth, cutoff times, and the column naming scheme.
|
|
66
|
+
- [Primitives](docs/guide/primitives.md) — what ships with tusk and how it behaves.
|
|
67
|
+
- [Custom primitives](docs/guide/custom-primitives.md) — the extension point.
|
|
68
|
+
- [scikit-learn pipelines](docs/guide/sklearn.md) — DFS as a pipeline step, and
|
|
69
|
+
computing only the features you keep.
|
|
70
|
+
- [Differences from featuretools](docs/guide/featuretools.md) — if you are porting.
|
|
71
|
+
- [API reference](docs/api/index.md) — every public symbol.
|
|
72
|
+
|
|
73
|
+
Build the site locally with:
|
|
74
|
+
|
|
75
|
+
```bash
|
|
76
|
+
uv run --group docs zensical serve
|
|
77
|
+
```
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "tusk-ml"
|
|
3
|
+
version = "0.1.0"
|
|
4
|
+
description = "Deep feature synthesis for narwhals dataframes"
|
|
5
|
+
readme = "README.md"
|
|
6
|
+
requires-python = ">=3.10"
|
|
7
|
+
dependencies = ["narwhals>=2.24"]
|
|
8
|
+
|
|
9
|
+
[project.optional-dependencies]
|
|
10
|
+
sklearn = ["scikit-learn>=1.4"]
|
|
11
|
+
|
|
12
|
+
[build-system]
|
|
13
|
+
requires = ["uv_build>=0.12.7,<0.13"]
|
|
14
|
+
build-backend = "uv_build"
|
|
15
|
+
|
|
16
|
+
[tool.uv.build-backend]
|
|
17
|
+
module-name = "tusk"
|
|
18
|
+
|
|
19
|
+
[tool.pytest.ini_options]
|
|
20
|
+
testpaths = [
|
|
21
|
+
"tests",
|
|
22
|
+
"benchmarks",
|
|
23
|
+
]
|
|
24
|
+
markers = [
|
|
25
|
+
"differential: cross-checks values against featuretools (opt-in)",
|
|
26
|
+
"benchmark: relbench performance runs (opt-in)",
|
|
27
|
+
]
|
|
28
|
+
addopts = "-m 'not differential and not benchmark'"
|
|
29
|
+
|
|
30
|
+
[tool.ruff.lint]
|
|
31
|
+
select = [
|
|
32
|
+
"E",
|
|
33
|
+
"F",
|
|
34
|
+
"I",
|
|
35
|
+
"UP",
|
|
36
|
+
"B",
|
|
37
|
+
"D",
|
|
38
|
+
]
|
|
39
|
+
|
|
40
|
+
[tool.ruff.lint.pydocstyle]
|
|
41
|
+
convention = "google"
|
|
42
|
+
|
|
43
|
+
[tool.ruff.lint.per-file-ignores]
|
|
44
|
+
"tests/*" = ["D"]
|
|
45
|
+
|
|
46
|
+
[tool.interrogate]
|
|
47
|
+
fail-under = 100
|
|
48
|
+
ignore-init-module = true
|
|
49
|
+
ignore-private = true
|
|
50
|
+
ignore-magic = true
|
|
51
|
+
ignore-nested-functions = true
|
|
52
|
+
exclude = [
|
|
53
|
+
"tests",
|
|
54
|
+
".venv",
|
|
55
|
+
".claude",
|
|
56
|
+
]
|
|
57
|
+
|
|
58
|
+
[tool.pydoclint]
|
|
59
|
+
style = "google"
|
|
60
|
+
exclude = "tests|benchmarks"
|
|
61
|
+
arg-type-hints-in-docstring = false
|
|
62
|
+
check-return-types = false
|
|
63
|
+
allow-init-docstring = true
|
|
64
|
+
|
|
65
|
+
[[tool.ty.overrides]]
|
|
66
|
+
include = [
|
|
67
|
+
"src/tusk/primitives/**",
|
|
68
|
+
"tests/**",
|
|
69
|
+
]
|
|
70
|
+
|
|
71
|
+
[tool.ty.overrides.rules]
|
|
72
|
+
invalid-method-override = "ignore"
|
|
73
|
+
|
|
74
|
+
[dependency-groups]
|
|
75
|
+
dev = [
|
|
76
|
+
"duckdb>=1.0",
|
|
77
|
+
"interrogate>=1.7.0",
|
|
78
|
+
"pre-commit-uv>=4.3.0",
|
|
79
|
+
"pydoclint>=0.9.1",
|
|
80
|
+
"pytest>=8.0",
|
|
81
|
+
"polars>=1.43",
|
|
82
|
+
"pyarrow>=17",
|
|
83
|
+
"ruff>=0.16.3",
|
|
84
|
+
"scikit-learn>=1.4",
|
|
85
|
+
"ty>=0.0.72",
|
|
86
|
+
]
|
|
87
|
+
validation = [
|
|
88
|
+
"featuretools>=1.31",
|
|
89
|
+
"pandas>=2.0",
|
|
90
|
+
"setuptools<81",
|
|
91
|
+
]
|
|
92
|
+
benchmark = [
|
|
93
|
+
"relbench>=2.1",
|
|
94
|
+
"duckdb>=1.0",
|
|
95
|
+
]
|
|
96
|
+
docs = [
|
|
97
|
+
"mkdocstrings[python]>=1.0.6",
|
|
98
|
+
"zensical>=0.0.56",
|
|
99
|
+
]
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "tusk-ml"
|
|
3
|
+
version = "0.1.0"
|
|
4
|
+
description = "Deep feature synthesis for narwhals dataframes"
|
|
5
|
+
readme = "README.md"
|
|
6
|
+
requires-python = ">=3.10"
|
|
7
|
+
dependencies = ["narwhals>=2.24"]
|
|
8
|
+
|
|
9
|
+
[project.optional-dependencies]
|
|
10
|
+
sklearn = ["scikit-learn>=1.4"]
|
|
11
|
+
|
|
12
|
+
[build-system]
|
|
13
|
+
requires = ["uv_build>=0.12.7,<0.13"]
|
|
14
|
+
build-backend = "uv_build"
|
|
15
|
+
|
|
16
|
+
[tool.uv.build-backend]
|
|
17
|
+
# The distribution is named tusk-ml because tusk is taken on PyPI; the
|
|
18
|
+
# import name stays tusk.
|
|
19
|
+
module-name = "tusk"
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
[dependency-groups]
|
|
23
|
+
dev = [
|
|
24
|
+
"duckdb>=1.0",
|
|
25
|
+
"interrogate>=1.7.0",
|
|
26
|
+
"pre-commit-uv>=4.3.0",
|
|
27
|
+
"pydoclint>=0.9.1",
|
|
28
|
+
"pytest>=8.0",
|
|
29
|
+
"polars>=1.43",
|
|
30
|
+
"pyarrow>=17",
|
|
31
|
+
"ruff>=0.16.3",
|
|
32
|
+
"scikit-learn>=1.4",
|
|
33
|
+
"ty>=0.0.72",
|
|
34
|
+
]
|
|
35
|
+
validation = [
|
|
36
|
+
"featuretools>=1.31",
|
|
37
|
+
"pandas>=2.0",
|
|
38
|
+
"setuptools<81",
|
|
39
|
+
]
|
|
40
|
+
benchmark = [
|
|
41
|
+
"relbench>=2.1",
|
|
42
|
+
"duckdb>=1.0",
|
|
43
|
+
]
|
|
44
|
+
docs = [
|
|
45
|
+
"mkdocstrings[python]>=1.0.6",
|
|
46
|
+
"zensical>=0.0.56",
|
|
47
|
+
]
|
|
48
|
+
|
|
49
|
+
[tool.pytest.ini_options]
|
|
50
|
+
testpaths = ["tests", "benchmarks"]
|
|
51
|
+
markers = [
|
|
52
|
+
"differential: cross-checks values against featuretools (opt-in)",
|
|
53
|
+
"benchmark: relbench performance runs (opt-in)",
|
|
54
|
+
]
|
|
55
|
+
addopts = "-m 'not differential and not benchmark'"
|
|
56
|
+
|
|
57
|
+
[tool.ruff.lint]
|
|
58
|
+
select = ["E", "F", "I", "UP", "B", "D"]
|
|
59
|
+
|
|
60
|
+
[tool.ruff.lint.pydocstyle]
|
|
61
|
+
convention = "google"
|
|
62
|
+
|
|
63
|
+
[tool.ruff.lint.per-file-ignores]
|
|
64
|
+
"tests/*" = ["D"]
|
|
65
|
+
|
|
66
|
+
[tool.interrogate]
|
|
67
|
+
fail-under = 100
|
|
68
|
+
ignore-init-module = true
|
|
69
|
+
ignore-private = true
|
|
70
|
+
ignore-magic = true
|
|
71
|
+
ignore-nested-functions = true
|
|
72
|
+
exclude = ["tests", ".venv", ".claude"]
|
|
73
|
+
|
|
74
|
+
[tool.pydoclint]
|
|
75
|
+
style = "google"
|
|
76
|
+
exclude = "tests|benchmarks"
|
|
77
|
+
arg-type-hints-in-docstring = false
|
|
78
|
+
check-return-types = false
|
|
79
|
+
# ruff (D107) and interrogate both require __init__ to carry its own
|
|
80
|
+
# docstring; without this flag pydoclint's DOC301 forbids exactly that
|
|
81
|
+
# whenever the class also has a docstring.
|
|
82
|
+
allow-init-docstring = true
|
|
83
|
+
|
|
84
|
+
[[tool.ty.overrides]]
|
|
85
|
+
include = ["src/tusk/primitives/**", "tests/**"]
|
|
86
|
+
|
|
87
|
+
[tool.ty.overrides.rules]
|
|
88
|
+
# Primitive.build is variadic in the ABC and fixed-arity in each concrete
|
|
89
|
+
# primitive. Arity is guaranteed by construction: synthesis supplies exactly
|
|
90
|
+
# len(input_dtypes) expressions to outputs(), which is build()'s only caller.
|
|
91
|
+
# Scoped rather than project-wide so override checking stays active everywhere
|
|
92
|
+
# else.
|
|
93
|
+
invalid-method-override = "ignore"
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"""Deep feature synthesis for narwhals dataframes."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from tusk import exceptions
|
|
6
|
+
from tusk.api import apply_features, deep_feature_synthesis
|
|
7
|
+
from tusk.database import Database, Relationship, TableSchema
|
|
8
|
+
from tusk.feature_list import FeatureList
|
|
9
|
+
|
|
10
|
+
__version__ = "0.1.0"
|
|
11
|
+
|
|
12
|
+
__all__ = [
|
|
13
|
+
"__version__",
|
|
14
|
+
"Database",
|
|
15
|
+
"FeatureList",
|
|
16
|
+
"Relationship",
|
|
17
|
+
"TableSchema",
|
|
18
|
+
"apply_features",
|
|
19
|
+
"deep_feature_synthesis",
|
|
20
|
+
"exceptions",
|
|
21
|
+
]
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
"""The public entry points.
|
|
2
|
+
|
|
3
|
+
:func:`deep_feature_synthesis` builds feature definitions and computes them;
|
|
4
|
+
:func:`apply_features` computes existing ones.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
from collections.abc import Iterable, Sequence
|
|
10
|
+
from datetime import datetime
|
|
11
|
+
from typing import Any
|
|
12
|
+
|
|
13
|
+
from tusk.database import Database
|
|
14
|
+
from tusk.feature_list import FeatureList
|
|
15
|
+
from tusk.features import Feature
|
|
16
|
+
from tusk.primitives.base import Primitive
|
|
17
|
+
from tusk.synthesis import synthesize
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def deep_feature_synthesis(
|
|
21
|
+
database: Database,
|
|
22
|
+
target_table: str,
|
|
23
|
+
agg_primitives: Iterable[str | Primitive] | None = None,
|
|
24
|
+
trans_primitives: Iterable[str | Primitive] | None = None,
|
|
25
|
+
groupby_trans_primitives: Iterable[str | Primitive] | None = None,
|
|
26
|
+
max_depth: int = 2,
|
|
27
|
+
cutoff_time: datetime | None = None,
|
|
28
|
+
features_only: bool = False,
|
|
29
|
+
) -> Any:
|
|
30
|
+
"""Run deep feature synthesis over a database.
|
|
31
|
+
|
|
32
|
+
Synthesis raises :class:`~tusk.exceptions.SchemaError` if the target table
|
|
33
|
+
is unknown or the walk generates no features at all, and
|
|
34
|
+
:class:`~tusk.exceptions.PrimitiveError` for an unknown primitive name or
|
|
35
|
+
an order-dependent primitive on a table with no ``row_creation_time``.
|
|
36
|
+
Compilation raises :class:`~tusk.exceptions.SchemaError` if the target
|
|
37
|
+
table has no ``primary_key``, and whatever :func:`apply_features`
|
|
38
|
+
documents for ``cutoff_time``.
|
|
39
|
+
|
|
40
|
+
Args:
|
|
41
|
+
database: The tables and relationships to synthesize over.
|
|
42
|
+
target_table: Table to build features for. The result has one
|
|
43
|
+
row per *visible* row of this table, keyed by its ``primary_key``.
|
|
44
|
+
With no ``cutoff_time`` that is every row; with one, the target is
|
|
45
|
+
filtered like any other table, so the matrix may have fewer rows.
|
|
46
|
+
agg_primitives: Aggregation primitives, as names or instances. None
|
|
47
|
+
selects the documented defaults.
|
|
48
|
+
trans_primitives: Transform primitives. None selects the defaults.
|
|
49
|
+
groupby_trans_primitives: Transforms applied within foreign-key groups.
|
|
50
|
+
None means none.
|
|
51
|
+
max_depth: Maximum number of stacked primitive applications.
|
|
52
|
+
cutoff_time: Only rows whose ``row_creation_time`` is at or before this
|
|
53
|
+
value are visible, on the target table as well as its relatives.
|
|
54
|
+
Its tz awareness must match the database's row creation times'.
|
|
55
|
+
A table with no ``row_creation_time`` is timeless and passes
|
|
56
|
+
through unfiltered, so a cutoff on a database that declares none is
|
|
57
|
+
silently a no-op. None disables filtering. Ignored entirely when
|
|
58
|
+
``features_only`` is true, since nothing is computed: the cutoff
|
|
59
|
+
belongs to compilation, and feature definitions do not record it.
|
|
60
|
+
features_only: Return the feature definitions without computing them.
|
|
61
|
+
|
|
62
|
+
Returns:
|
|
63
|
+
feature_matrix: An uncomputed query plan in the caller's native frame
|
|
64
|
+
type. On a backend with a lazy frame type you get one back, so call
|
|
65
|
+
``.collect()`` to compute it. Not returned when ``features_only``
|
|
66
|
+
is true.
|
|
67
|
+
features (FeatureList): The feature definitions, reusable with
|
|
68
|
+
:meth:`~tusk.FeatureList.apply` or :func:`apply_features`.
|
|
69
|
+
|
|
70
|
+
Warns:
|
|
71
|
+
CategoricalDtypeWarning: If a Categorical or Enum column is skipped
|
|
72
|
+
because a requested primitive requires a string input.
|
|
73
|
+
UnmatchedPrimitiveWarning: If a requested primitive matched no column
|
|
74
|
+
of its input dtypes anywhere in the walk.
|
|
75
|
+
"""
|
|
76
|
+
features = synthesize(
|
|
77
|
+
database=database,
|
|
78
|
+
target_table=target_table,
|
|
79
|
+
agg_primitives=agg_primitives,
|
|
80
|
+
trans_primitives=trans_primitives,
|
|
81
|
+
groupby_trans_primitives=groupby_trans_primitives,
|
|
82
|
+
max_depth=max_depth,
|
|
83
|
+
)
|
|
84
|
+
if features_only:
|
|
85
|
+
return features
|
|
86
|
+
return features.apply(database, cutoff_time), features
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
def apply_features(
|
|
90
|
+
features: Sequence[Feature],
|
|
91
|
+
database: Database,
|
|
92
|
+
cutoff_time: datetime | None = None,
|
|
93
|
+
) -> Any:
|
|
94
|
+
"""Apply existing feature definitions to a database.
|
|
95
|
+
|
|
96
|
+
Use this to apply a feature set fitted on training data to new data. It
|
|
97
|
+
accepts any sequence of features; a :class:`~tusk.FeatureList` can compute
|
|
98
|
+
itself with :meth:`~tusk.FeatureList.apply` instead.
|
|
99
|
+
|
|
100
|
+
Raises :class:`~tusk.exceptions.SchemaError` if ``features`` is empty,
|
|
101
|
+
spans more than one table, or targets a table with no ``primary_key``, and
|
|
102
|
+
:class:`~tusk.exceptions.PrimitiveError` if an order-dependent primitive
|
|
103
|
+
lands on a table with no ``row_creation_time``.
|
|
104
|
+
:class:`~tusk.exceptions.ValidationError` is raised if ``cutoff_time``
|
|
105
|
+
differs from the database's row creation times in tz awareness, or if
|
|
106
|
+
those disagree among themselves, and ``TypeError`` if ``cutoff_time`` is
|
|
107
|
+
not a ``datetime``.
|
|
108
|
+
|
|
109
|
+
Args:
|
|
110
|
+
features: Feature definitions, all on the same target table.
|
|
111
|
+
database: The database to compute over.
|
|
112
|
+
cutoff_time: Only rows whose ``row_creation_time`` is at or before this
|
|
113
|
+
value are visible, on the target table as well as its relatives, so
|
|
114
|
+
the matrix may have fewer rows than the target. Its tz awareness
|
|
115
|
+
must match the database's row creation times'. A table with no
|
|
116
|
+
``row_creation_time`` is timeless and passes through unfiltered,
|
|
117
|
+
so a cutoff on a database that declares none is silently a no-op.
|
|
118
|
+
None disables filtering.
|
|
119
|
+
|
|
120
|
+
Returns:
|
|
121
|
+
feature_matrix: An uncomputed query plan in the caller's native frame
|
|
122
|
+
type, with one row per visible target row. tusk never collects, so
|
|
123
|
+
on a backend with a lazy frame type you decide when to compute.
|
|
124
|
+
"""
|
|
125
|
+
return FeatureList(features).apply(database, cutoff_time)
|