Skip to main content

featkit — automated feature store generation from relational facts tables

Project description

featkit

featkit is a Python framework for automated feature store generation from relational facts tables.

It implements a three-layer architecture:

  • Layer 1 — input facts table with typed columns (ID, time, categorical, measurement)
  • Layer 2 — horizontal concept table built via pivot (2A) and distributional aggregations (2B)
  • Layer 3 — temporal feature table produced by sliding operators over the Layer 2 columns

The framework is engine-agnostic: the same pipeline definition produces either a standalone SQL script (Snowflake, Databricks SQL, Spark SQL) or a lazy PySpark execution plan, with the choice abstracted behind a code generator interface.

Key concepts

Layer What it does
Layer 2A — Pivot GROUP BY (ID, time) + CASE WHEN per categorical combination × measurement × aggregator
Layer 2B — Distributional Per-categorical CTEs computing entropy, HHI, dominant proportion, mode, count
Layer 3 — Temporal Sliding window operators (PROM_U, SUM_U, CREC, FREQ, REC, …) over all Layer 2 columns

Installation

pip install featkit

Quickstart

from featkit import FeatureStorePipeline, FeatureStoreConfig
from featkit.dataset import SimpleDataset
from featkit.fields import IDField, TimeField, CategoricalField, MeasurementField
from featkit.enums import MeasurementType, TimeGranularity, CategoricalTreatment
from featkit.generators.sql import SnowflakeSQLCodeGenerator

# Define schema
fields = [
    IDField(name="ID_CLIENTE"),
    TimeField(name="PERIODO",
              source_granularity=TimeGranularity.MONTHLY,
              target_granularity=TimeGranularity.MONTHLY),
    CategoricalField(name="SECTOR", treatment=CategoricalTreatment.PIVOT,
                     allowed_values=["RETAIL", "CORP", "PYME"]),
    CategoricalField(name="CANAL",  treatment=CategoricalTreatment.PIVOT,
                     allowed_values=["DIGITAL", "PRESENCIAL", "TELEFONO"]),
    MeasurementField(name="MTO", measurement_type=MeasurementType.MONTO),
    MeasurementField(name="TRX", measurement_type=MeasurementType.CANTIDAD),
]

dataset = SimpleDataset(
    source_reference="MY_DB.MY_SCHEMA.FACTS_TABLE",
    fields=fields,
)

config = FeatureStoreConfig(
    dataset=dataset,
    output_schema="MY_DB.MY_SCHEMA",
    output_table_prefix="FS",
    time_windows=[3, 6, 9, 12],
)

pipeline = FeatureStorePipeline(config).build()
output = pipeline.run(SnowflakeSQLCodeGenerator())

output.save("./output")
# Writes: output/script.sql, output/dag.json, output/diagram.md

Feature naming anatomy

Every feature produced by featkit has a deterministic, human-readable name built from fixed segments separated by __ (double underscore). Understanding the segments lets you decode any feature name without looking at the code.

There are four families of features, each with its own naming pattern.


Layer 2A — Pivot features

Pattern: {AGG}__{MEASUREMENT}[__{FIELD}_{VALUE}…]

Segment Source Example
AGG Layer2Aggregator enum SUM, COUNT, AVG, MIN, MAX
MEASUREMENT MeasurementField.name MTO, TRX
FIELD_VALUE CategoricalField.name + _ + value, one per non-marginal field, sorted alphabetically by field name CANAL_DIGITAL, SECTOR_RETAIL

The valid aggregators for each MEASUREMENT depend on its MeasurementType. Only contract-permitted aggregator–measurement combinations are generated.

Measurement type Semantic meaning Valid AGG values
MONTO Monetary amount SUM, MAX, MIN, AVG
CANTIDAD Count / quantity SUM
TICKET Average ticket size AVG
FLAG Binary indicator MAX
FECHA Date / timestamp MAX, MIN
BALANCE Point-in-time balance MAX, MIN, AVG
TIME_DIFF Duration / elapsed time SUM, AVG, MAX, MIN
ESTADISTICO Generic statistic SUM, AVG, MAX, MIN, COUNT

Categorical fields set to the ∅ marginal (no filter on that dimension) are omitted from the name entirely, so the name implicitly aggregates over all values of that dimension.

SUM__MTO                                  # global — all sectors, all channels
SUM__MTO__CANAL_DIGITAL                   # CANAL=DIGITAL, marginal over SECTOR
SUM__MTO__SECTOR_RETAIL                   # SECTOR=RETAIL, marginal over CANAL
SUM__MTO__CANAL_DIGITAL__SECTOR_RETAIL    # CANAL=DIGITAL and SECTOR=RETAIL (alphabetical order)
SUM__TRX__CANAL_PRESENCIAL                # sum of TRX (CANTIDAD → only SUM is valid) for PRESENCIAL channel

Layer 2B — Distributional features

Pattern: {CATEGORICAL}__{MEASUREMENT}__{AGG}__{METRIC}

Segment Source Example
CATEGORICAL CategoricalField.name CANAL, SECTOR
MEASUREMENT MeasurementField.name MTO
AGG Layer2Aggregator enum SUM
METRIC DistributionalMetric enum ENTROPY, HHI, DOMINANT_PROPORTION, MODE, COUNT

These columns capture the shape of the value distribution of a categorical field, weighted by the aggregated measurement.

Metric What it measures
ENTROPY Shannon entropy of the category distribution — higher means more uniform spread
HHI Herfindahl-Hirschman Index — concentration; higher means more dominated by one value
DOMINANT_PROPORTION Share of the most common category value
MODE The most frequent category value (output type: categorical)
COUNT Number of distinct observed values
CANAL__MTO__SUM__ENTROPY            # entropy of channel distribution by amount
SECTOR__TRX__SUM__HHI               # HHI of sector distribution by transaction count (CANTIDAD → only SUM)
CANAL__MTO__SUM__MODE               # dominant channel by amount (categorical output)

Layer 2C — Ratio features

Pattern: {NUMERATOR}__over__{DENOMINATOR}

where NUMERATOR and DENOMINATOR are full Layer 2A pivot feature names. The denominator is always a proper marginal projection of the numerator: it has at least one categorical dimension set to ∅ that is non-∅ in the numerator, and no contradicting values.

The underlying value is numerator / NULLIF(denominator, 0) computed per entity per period.

# Numerator: DIGITAL channel + RETAIL sector
# Denominator: RETAIL sector only (CANAL marginalized → share of DIGITAL within RETAIL)
SUM__MTO__CANAL_DIGITAL__SECTOR_RETAIL__over__SUM__MTO__SECTOR_RETAIL

# Denominator: DIGITAL channel only (SECTOR marginalized → share of RETAIL within DIGITAL)
SUM__MTO__CANAL_DIGITAL__SECTOR_RETAIL__over__SUM__MTO__CANAL_DIGITAL

# Denominator: global total (both marginalized → share of DIGITAL/RETAIL in total portfolio)
SUM__MTO__CANAL_DIGITAL__SECTOR_RETAIL__over__SUM__MTO

Layer 3 — Temporal features

Pattern: {L2_NAME}__{OPERATOR}__{DIRECTION}[__{WINDOW}]

L2_NAME is the full name of any Layer 2A, 2B, or 2C feature. The temporal segments are appended at the end.

Segment Source Notes
OPERATOR TemporalOperator enum See table below
DIRECTION TimeWindowDirection enum BACKWARD or FORWARD
WINDOW window_size (integer, number of periods) Omitted for point-in-time operators

Temporal operators

Operator Type Description
PROM_U Windowed Arithmetic mean of the monthly values over the window — each period contributes equally regardless of its volume
PROM_P Windowed Volume-proportional weighted mean — each period's contribution is weighted by its share of the total aggregated value across the window; weights are derived automatically from the data, no user configuration required
SUM_U Windowed Unweighted sum of the monthly values over the window
SUM_P Windowed Volume-weighted sum over the window (analogous weighting to PROM_P)
MIN_U Windowed Minimum value observed in the window
MAX_U Windowed Maximum value observed in the window
CREC Windowed Growth rate across the window
FREQ Windowed Count of periods in the window where the value was non-null and strictly greater than 0
XM Windowed 1 if every period in the window had a non-null and strictly positive value, 0 otherwise — an all-or-nothing activity indicator (e.g. 1 means the customer was active on every single month in the window)
MEDIA_ABS Windowed (composed) Mean absolute deviation over the window
RATIO Windowed (composed) Ratio of two sub-windows
ULT_MES Point-in-time Value at the most recent period (no window suffix)
PREV_MES Point-in-time Value at the immediately preceding period (no window suffix)
REC Point-in-time Recency — periods elapsed since last non-null / non-zero observation (no window suffix)

Valid operators per Layer 2 output type

Output type Valid operators
NUMERIC PROM_U, PROM_P, SUM_U, SUM_P, MIN_U, MAX_U, CREC, FREQ, XM, ULT_MES, PREV_MES, MEDIA_ABS, RATIO
FLAG ULT_MES, PREV_MES, FREQ, XM, REC
CATEGORICAL ULT_MES, PREV_MES, REC
TEMPORAL ULT_MES, PREV_MES, REC, MIN_U, MAX_U, CREC

Examples

# Average amount (DIGITAL + RETAIL) over the last 6 months
SUM__MTO__CANAL_DIGITAL__SECTOR_RETAIL__PROM_U__BACKWARD__6

# Total transaction sum for RETAIL sector in the last 3 months (CANTIDAD → only SUM valid)
SUM__TRX__SECTOR_RETAIL__SUM_U__BACKWARD__3

# Most recent value of the CANAL entropy (by amount)
CANAL__MTO__SUM__ENTROPY__ULT_MES__BACKWARD

# Share of DIGITAL/RETAIL in total portfolio, averaged over last 12 months
SUM__MTO__CANAL_DIGITAL__SECTOR_RETAIL__over__SUM__MTO__PROM_U__BACKWARD__12

# Recency of the dominant channel (MODE is categorical → only REC/ULT_MES/PREV_MES valid)
CANAL__MTO__SUM__MODE__REC__BACKWARD

Quick-reference: full name structure

┌─ Layer 2A pivot ──────────────────────────────────────────────────┐
│  AGG  __  MEASUREMENT  [__  FIELD_VALUE  …]                       │
└───────────────────────────────────────────────────────────────────┘

┌─ Layer 2B distributional ─────────────────────────────────────────┐
│  CATEGORICAL  __  MEASUREMENT  __  AGG  __  METRIC                │
└───────────────────────────────────────────────────────────────────┘

┌─ Layer 2C ratio ──────────────────────────────────────────────────┐
│  {Layer 2A name}  __over__  {Layer 2A name}                       │
└───────────────────────────────────────────────────────────────────┘

┌─ Layer 3 temporal (windowed) ─────────────────────────────────────┐
│  {Layer 2A/2B/2C name}  __  OPERATOR  __  DIRECTION  __  WINDOW   │
└───────────────────────────────────────────────────────────────────┘

┌─ Layer 3 temporal (point-in-time) ────────────────────────────────┐
│  {Layer 2A/2B/2C name}  __  OPERATOR  __  DIRECTION               │
└───────────────────────────────────────────────────────────────────┘

Architecture

See docs/general_plan.md for the full implementation plan.

License

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

featkit-0.4.2.tar.gz (80.0 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

featkit-0.4.2-py3-none-any.whl (61.8 kB view details)

Uploaded Python 3

File details

Details for the file featkit-0.4.2.tar.gz.

File metadata

  • Download URL: featkit-0.4.2.tar.gz
  • Upload date:
  • Size: 80.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for featkit-0.4.2.tar.gz
Algorithm Hash digest
SHA256 2b225a0801705481e17f68ed463f25cfa253264e2aa8de818683b6fc8d801fc5
MD5 183c48930c10e2e559e6eb176d13841b
BLAKE2b-256 9885cea845a7578df7ccf22a5c6c53cd80d9fb93b4d3e8ded6e006a3df0f8e05

See more details on using hashes here.

Provenance

The following attestation bundles were made for featkit-0.4.2.tar.gz:

Publisher: publish.yml on Mirkiux/featkit

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file featkit-0.4.2-py3-none-any.whl.

File metadata

  • Download URL: featkit-0.4.2-py3-none-any.whl
  • Upload date:
  • Size: 61.8 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for featkit-0.4.2-py3-none-any.whl
Algorithm Hash digest
SHA256 0a831691424d3cb94b800780f2d99d86ab6795d0020f5f8ee7fa7ebceb60bda1
MD5 812df14e363afb6853ca7e47514577cc
BLAKE2b-256 258f9daac43ee0c5dd1e3473c17676aedca8492d211600016aba0071774b7818

See more details on using hashes here.

Provenance

The following attestation bundles were made for featkit-0.4.2-py3-none-any.whl:

Publisher: publish.yml on Mirkiux/featkit

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page