xplainable-preprocessing 0.2.3__tar.gz → 0.2.4__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.
Files changed (40) hide show
  1. {xplainable_preprocessing-0.2.3 → xplainable_preprocessing-0.2.4}/PKG-INFO +3 -2
  2. {xplainable_preprocessing-0.2.3 → xplainable_preprocessing-0.2.4}/pyproject.toml +2 -1
  3. {xplainable_preprocessing-0.2.3 → xplainable_preprocessing-0.2.4}/src/xplainable_preprocessing/pipeline.py +6 -0
  4. xplainable_preprocessing-0.2.4/tests/test_pipeline.py +73 -0
  5. {xplainable_preprocessing-0.2.3 → xplainable_preprocessing-0.2.4}/.github/workflows/publish-pypi.yml +0 -0
  6. {xplainable_preprocessing-0.2.3 → xplainable_preprocessing-0.2.4}/.gitignore +0 -0
  7. {xplainable_preprocessing-0.2.3 → xplainable_preprocessing-0.2.4}/README.md +0 -0
  8. {xplainable_preprocessing-0.2.3 → xplainable_preprocessing-0.2.4}/docs/dag-pipeline-proposal.md +0 -0
  9. {xplainable_preprocessing-0.2.3 → xplainable_preprocessing-0.2.4}/docs/feature-pipeline-architectures.md +0 -0
  10. {xplainable_preprocessing-0.2.3 → xplainable_preprocessing-0.2.4}/docs/feature-store-proposal.md +0 -0
  11. {xplainable_preprocessing-0.2.3 → xplainable_preprocessing-0.2.4}/src/xplainable_preprocessing/__init__.py +0 -0
  12. {xplainable_preprocessing-0.2.3 → xplainable_preprocessing-0.2.4}/src/xplainable_preprocessing/compiler.py +0 -0
  13. {xplainable_preprocessing-0.2.3 → xplainable_preprocessing-0.2.4}/src/xplainable_preprocessing/preview.py +0 -0
  14. {xplainable_preprocessing-0.2.3 → xplainable_preprocessing-0.2.4}/src/xplainable_preprocessing/registry.py +0 -0
  15. {xplainable_preprocessing-0.2.3 → xplainable_preprocessing-0.2.4}/src/xplainable_preprocessing/sandbox.py +0 -0
  16. {xplainable_preprocessing-0.2.3 → xplainable_preprocessing-0.2.4}/src/xplainable_preprocessing/schema.py +0 -0
  17. {xplainable_preprocessing-0.2.3 → xplainable_preprocessing-0.2.4}/src/xplainable_preprocessing/serialization.py +0 -0
  18. {xplainable_preprocessing-0.2.3 → xplainable_preprocessing-0.2.4}/src/xplainable_preprocessing/transformers/__init__.py +0 -0
  19. {xplainable_preprocessing-0.2.3 → xplainable_preprocessing-0.2.4}/src/xplainable_preprocessing/transformers/category_condense.py +0 -0
  20. {xplainable_preprocessing-0.2.3 → xplainable_preprocessing-0.2.4}/src/xplainable_preprocessing/transformers/clip.py +0 -0
  21. {xplainable_preprocessing-0.2.3 → xplainable_preprocessing-0.2.4}/src/xplainable_preprocessing/transformers/datetime_extract.py +0 -0
  22. {xplainable_preprocessing-0.2.3 → xplainable_preprocessing-0.2.4}/src/xplainable_preprocessing/transformers/drop_columns.py +0 -0
  23. {xplainable_preprocessing-0.2.3 → xplainable_preprocessing-0.2.4}/src/xplainable_preprocessing/transformers/expression.py +0 -0
  24. {xplainable_preprocessing-0.2.3 → xplainable_preprocessing-0.2.4}/src/xplainable_preprocessing/transformers/fill_missing.py +0 -0
  25. {xplainable_preprocessing-0.2.3 → xplainable_preprocessing-0.2.4}/src/xplainable_preprocessing/transformers/groupby_agg.py +0 -0
  26. {xplainable_preprocessing-0.2.3 → xplainable_preprocessing-0.2.4}/src/xplainable_preprocessing/transformers/grouped_lag.py +0 -0
  27. {xplainable_preprocessing-0.2.3 → xplainable_preprocessing-0.2.4}/src/xplainable_preprocessing/transformers/missing_flag.py +0 -0
  28. {xplainable_preprocessing-0.2.3 → xplainable_preprocessing-0.2.4}/src/xplainable_preprocessing/transformers/rename_columns.py +0 -0
  29. {xplainable_preprocessing-0.2.3 → xplainable_preprocessing-0.2.4}/src/xplainable_preprocessing/transformers/rolling_agg.py +0 -0
  30. {xplainable_preprocessing-0.2.3 → xplainable_preprocessing-0.2.4}/src/xplainable_preprocessing/transformers/text_clean.py +0 -0
  31. {xplainable_preprocessing-0.2.3 → xplainable_preprocessing-0.2.4}/src/xplainable_preprocessing/transformers/type_cast.py +0 -0
  32. {xplainable_preprocessing-0.2.3 → xplainable_preprocessing-0.2.4}/tests/__init__.py +0 -0
  33. {xplainable_preprocessing-0.2.3 → xplainable_preprocessing-0.2.4}/tests/test_compiler.py +0 -0
  34. {xplainable_preprocessing-0.2.3 → xplainable_preprocessing-0.2.4}/tests/test_preview.py +0 -0
  35. {xplainable_preprocessing-0.2.3 → xplainable_preprocessing-0.2.4}/tests/test_sandbox.py +0 -0
  36. {xplainable_preprocessing-0.2.3 → xplainable_preprocessing-0.2.4}/tests/test_schema.py +0 -0
  37. {xplainable_preprocessing-0.2.3 → xplainable_preprocessing-0.2.4}/tests/test_serialization.py +0 -0
  38. {xplainable_preprocessing-0.2.3 → xplainable_preprocessing-0.2.4}/tests/test_transformers/__init__.py +0 -0
  39. {xplainable_preprocessing-0.2.3 → xplainable_preprocessing-0.2.4}/tests/test_transformers/test_all_transformers.py +0 -0
  40. {xplainable_preprocessing-0.2.3 → xplainable_preprocessing-0.2.4}/tests/test_transformers/test_expression.py +0 -0
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.4
1
+ Metadata-Version: 2.5
2
2
  Name: xplainable-preprocessing
3
- Version: 0.2.3
3
+ Version: 0.2.4
4
4
  Summary: Shared preprocessing pipeline package for xplainable
5
5
  Requires-Python: >=3.9
6
6
  Requires-Dist: cloudpickle>=3.0
@@ -8,6 +8,7 @@ Requires-Dist: numpy>=1.24
8
8
  Requires-Dist: pandas>=2.0
9
9
  Requires-Dist: pydantic>=2.0
10
10
  Requires-Dist: scikit-learn>=1.3
11
+ Requires-Dist: scipy>=1.8
11
12
  Provides-Extra: dev
12
13
  Requires-Dist: pytest-cov; extra == 'dev'
13
14
  Requires-Dist: pytest>=7.0; extra == 'dev'
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "xplainable-preprocessing"
7
- version = "0.2.3"
7
+ version = "0.2.4"
8
8
  description = "Shared preprocessing pipeline package for xplainable"
9
9
  requires-python = ">=3.9"
10
10
  dependencies = [
@@ -12,6 +12,7 @@ dependencies = [
12
12
  "scikit-learn>=1.3",
13
13
  "pandas>=2.0",
14
14
  "numpy>=1.24",
15
+ "scipy>=1.8",
15
16
  "cloudpickle>=3.0",
16
17
  ]
17
18
 
@@ -3,6 +3,7 @@
3
3
  from __future__ import annotations
4
4
 
5
5
  import pandas as pd
6
+ from scipy import sparse
6
7
  from sklearn.base import BaseEstimator, TransformerMixin
7
8
 
8
9
 
@@ -20,6 +21,11 @@ class DataFrameColumnTransformer(BaseEstimator, TransformerMixin):
20
21
  def transform(self, X: pd.DataFrame) -> pd.DataFrame:
21
22
  Xt = X.copy()
22
23
  result = self.transformer.transform(Xt[self.columns])
24
+ if sparse.issparse(result):
25
+ # e.g. OneHotEncoder defaults to sparse_output=True; pd.DataFrame
26
+ # would treat the matrix as a single object column and raise
27
+ # "Shape of passed values is (N, 1), indices imply (N, K)".
28
+ result = result.toarray()
23
29
  if isinstance(result, pd.DataFrame):
24
30
  Xt = Xt.drop(columns=self.columns)
25
31
  Xt = pd.concat([Xt, result], axis=1)
@@ -0,0 +1,73 @@
1
+ """Tests for DataFrame-preserving pipeline pieces.
2
+
3
+ Regression coverage for sparse transformer output: sklearn's OneHotEncoder
4
+ defaults to sparse_output=True (csr_matrix). pd.DataFrame(csr_matrix, ...)
5
+ treats the matrix as a single object column, raising
6
+ "Shape of passed values is (N, 1), indices imply (N, K)".
7
+ Observed live as HTTP 500s from /v1/preprocessors/create.
8
+ """
9
+
10
+ import pandas as pd
11
+ import pytest
12
+ from sklearn.preprocessing import OneHotEncoder
13
+
14
+ from xplainable_preprocessing.compiler import compile_spec
15
+ from xplainable_preprocessing.pipeline import DataFrameColumnTransformer
16
+ from xplainable_preprocessing.schema import PipelineSpec
17
+
18
+
19
+ @pytest.fixture
20
+ def df():
21
+ return pd.DataFrame({
22
+ "PhoneService": ["Yes", "No"] * 25,
23
+ "Contract": ["Month-to-month", "One year", "Two year", "One year",
24
+ "Month-to-month"] * 10,
25
+ "tenure": range(50),
26
+ })
27
+
28
+
29
+ class TestSparseTransformerOutput:
30
+ def test_column_transformer_densifies_sparse_output(self, df):
31
+ t = DataFrameColumnTransformer(OneHotEncoder(), ["PhoneService", "Contract"])
32
+ out = t.fit_transform(df)
33
+
34
+ assert isinstance(out, pd.DataFrame)
35
+ assert "tenure" in out.columns
36
+ assert "PhoneService_Yes" in out.columns
37
+ assert "Contract_Two year" in out.columns
38
+ # Row 0: PhoneService == "Yes"
39
+ assert out.loc[0, "PhoneService_Yes"] == 1.0
40
+ assert out.loc[0, "PhoneService_No"] == 0.0
41
+
42
+ def test_compile_spec_onehot_multi_column_step(self, df):
43
+ spec = PipelineSpec(version="2.0", steps=[
44
+ {"id": "oh", "type": "OneHotEncoder",
45
+ "columns": ["PhoneService", "Contract"], "params": {}},
46
+ ])
47
+ pipeline = compile_spec(spec)
48
+ out = pipeline.fit_transform(df)
49
+
50
+ assert "PhoneService" not in out.columns
51
+ assert "PhoneService_No" in out.columns
52
+ assert "Contract_One year" in out.columns
53
+ assert len(out) == 50
54
+
55
+ def test_compile_spec_onehot_one_column_per_step(self, df):
56
+ spec = PipelineSpec(version="2.0", steps=[
57
+ {"id": "oh1", "type": "OneHotEncoder",
58
+ "columns": ["PhoneService"], "params": {}},
59
+ {"id": "oh2", "type": "OneHotEncoder",
60
+ "columns": ["Contract"], "params": {}},
61
+ ])
62
+ pipeline = compile_spec(spec)
63
+ out = pipeline.fit_transform(df)
64
+
65
+ assert "PhoneService_Yes" in out.columns
66
+ assert "Contract_Month-to-month" in out.columns
67
+ assert "tenure" in out.columns
68
+
69
+ def test_transform_after_fit_matches_fit_transform(self, df):
70
+ t = DataFrameColumnTransformer(OneHotEncoder(), ["PhoneService"])
71
+ fitted_out = t.fit_transform(df)
72
+ transform_out = t.transform(df)
73
+ pd.testing.assert_frame_equal(fitted_out, transform_out)