spforge 0.8.7__py3-none-any.whl → 0.8.9__py3-none-any.whl

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.

Potentially problematic release.


This version of spforge might be problematic. Click here for more details.

@@ -120,7 +120,8 @@ class FeatureGeneratorPipeline(FeatureGenerator):
120
120
 
121
121
  for transformer in self.feature_generators:
122
122
  pre_row_count = len(df)
123
- df = nw.from_native(transformer.fit_transform(df, column_names=column_names))
123
+ native_df = df.to_native()
124
+ df = nw.from_native(transformer.fit_transform(native_df, column_names=column_names))
124
125
  assert len(df) == pre_row_count
125
126
  for f in transformer.features_out:
126
127
  if f in expected_feats_added:
@@ -151,7 +152,8 @@ class FeatureGeneratorPipeline(FeatureGenerator):
151
152
 
152
153
  for transformer in self.feature_generators:
153
154
  pre_row_count = len(df)
154
- df = nw.from_native(transformer.transform(df))
155
+ native_df = df.to_native()
156
+ df = nw.from_native(transformer.transform(native_df))
155
157
  assert len(df) == pre_row_count
156
158
  for f in transformer.features_out:
157
159
  if f in expected_feats_added:
@@ -181,9 +183,11 @@ class FeatureGeneratorPipeline(FeatureGenerator):
181
183
  for transformer in self.feature_generators:
182
184
  pre_row_count = len(df)
183
185
  if hasattr(transformer, "future_transform") and callable(transformer.future_transform):
184
- df = nw.from_native(transformer.future_transform(df))
186
+ native_df = df.to_native()
187
+ df = nw.from_native(transformer.future_transform(native_df))
185
188
  else:
186
- df = nw.from_native(transformer.transform(df))
189
+ native_df = df.to_native()
190
+ df = nw.from_native(transformer.transform(native_df))
187
191
  assert len(df) == pre_row_count
188
192
  for f in transformer.features_out:
189
193
  if f in expected_feats_added:
@@ -250,8 +250,6 @@ class PerformanceWeightsManager(PerformanceManager):
250
250
  )
251
251
  )
252
252
 
253
- sum_weight = sum([w.weight for w in self.weights])
254
-
255
253
  for column_weight in self.weights:
256
254
  weight_col = f"weight__{column_weight.name}"
257
255
  feature_col = column_weight.name
@@ -261,14 +259,14 @@ class PerformanceWeightsManager(PerformanceManager):
261
259
  df = df.with_columns(
262
260
  (
263
261
  nw.col(tmp_out_performance_colum_name)
264
- + (nw.col(weight_col) / sum_weight * (1 - nw.col(feature_name)))
262
+ + (nw.col(weight_col) * (1 - nw.col(feature_name)))
265
263
  ).alias(tmp_out_performance_colum_name)
266
264
  )
267
265
  else:
268
266
  df = df.with_columns(
269
267
  (
270
268
  nw.col(tmp_out_performance_colum_name)
271
- + (nw.col(weight_col) / sum_weight * nw.col(feature_name))
269
+ + (nw.col(weight_col) * nw.col(feature_name))
272
270
  ).alias(tmp_out_performance_colum_name)
273
271
  )
274
272
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: spforge
3
- Version: 0.8.7
3
+ Version: 0.8.9
4
4
  Summary: A flexible framework for generating features, ratings, and building machine learning or other models for training and inference on sports data.
5
5
  Author-email: Mathias Holmstrøm <mathiasholmstom@gmail.com>
6
6
  License: See LICENSE file
@@ -17,7 +17,7 @@ spforge/__init__.py,sha256=8vZhy7XUpzqWkVKpXqwqOLDkQlNytRhyf4qjwObfXgU,468
17
17
  spforge/autopipeline.py,sha256=ZUwv6Q6O8cD0u5TiSqG6lhW0j16RlSb160AzuOeL2R8,23186
18
18
  spforge/base_feature_generator.py,sha256=RbD00N6oLCQQcEb_VF5wbwZztl-X8k9B0Wlaj9Os1iU,668
19
19
  spforge/data_structures.py,sha256=k82v5r79vl0_FAVvsxVF9Nbzb5FoHqVrlHZlEXGc5gQ,7298
20
- spforge/features_generator_pipeline.py,sha256=KRLv03QNgXH4DvPEgpin8g0TQEelDik3Ynec12E1o20,8016
20
+ spforge/features_generator_pipeline.py,sha256=n8vzZKqXNFcFRDWZhllnkhAh5NFXdOD3FEIOpHcay8E,8208
21
21
  spforge/utils.py,sha256=2RlivUtMX5wQWpFVUyFfexDJE0wV6uZ4dnNzvoDmVhI,2644
22
22
  spforge/cross_validator/__init__.py,sha256=1QHgTFIZ73EZ_MgJlUKimxdUmB7MFaOEy6jsUs6V0T0,134
23
23
  spforge/cross_validator/_base.py,sha256=-zxZ2Q2tYlGIwjQQMf9_OglS_doppp47gVElkJuBY7E,1199
@@ -47,7 +47,7 @@ spforge/hyperparameter_tuning/__init__.py,sha256=N2sKG4SvG41hlsFT2kx_DQYMmXsQr-8
47
47
  spforge/hyperparameter_tuning/_default_search_spaces.py,sha256=Sm5IrHAW0-vRC8jqCPX0pDi_C-W3L_MoEKGA8bx1Zbc,7546
48
48
  spforge/hyperparameter_tuning/_tuner.py,sha256=uovhGqhe8-fdhi79aErUmE2h5NCycFQEIRv5WCjpC7E,16732
49
49
  spforge/performance_transformers/__init__.py,sha256=U6d7_kltbUMLYCGBk4QAFVPJTxXD3etD9qUftV-O3q4,422
50
- spforge/performance_transformers/_performance_manager.py,sha256=KwAga6dGhNkXi-MDW6LPjwk6VZwCcjo5L--jnk9aio8,9706
50
+ spforge/performance_transformers/_performance_manager.py,sha256=WmjmlMEnq7y75MiI_s9Y-9eMXIyhPTUKrwsXRtgYp0k,9620
51
51
  spforge/performance_transformers/_performances_transformers.py,sha256=0lxuWjAfWBRXRgQsNJHjw3P-nlTtHBu4_bOVdoy7hq4,15536
52
52
  spforge/ratings/__init__.py,sha256=OZVH2Lo6END3n1X8qi4QcyAPlThIwAYwVKCiIuOQSQU,576
53
53
  spforge/ratings/_base.py,sha256=dRMkIGj5-2zKddygaEA4g16WCyXon7v8Xa1ymm7IuoM,14335
@@ -71,10 +71,10 @@ spforge/transformers/_other_transformer.py,sha256=xLfaFIhkFsigAoitB4x3F8An2j9ymd
71
71
  spforge/transformers/_predictor.py,sha256=2sE6gfVrilXzPVcBurSrtqHw33v2ljygQcEYXt9LhZc,3119
72
72
  spforge/transformers/_simple_transformer.py,sha256=zGUFNQYMeoDSa2CoQejQNiNmKCBN5amWTvyOchiUHj0,5660
73
73
  spforge/transformers/_team_ratio_predictor.py,sha256=g8_bR53Yyv0iNCtol1O9bgJSeZcIco_AfbQuUxQJkeY,6884
74
- spforge-0.8.7.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
74
+ spforge-0.8.9.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
75
75
  tests/test_autopipeline.py,sha256=WXHeqBdjQD6xaXVkzvS8ocz0WVP9R7lN0PiHJ2iD8nA,16911
76
76
  tests/test_autopipeline_context.py,sha256=IuRUY4IA6uMObvbl2pXSaXO2_tl3qX6wEbTZY0dkTMI,1240
77
- tests/test_feature_generator_pipeline.py,sha256=CAgBknWqawqYi5_hxcPmpxrLVa5elMHVv1VrSVRKXEA,17705
77
+ tests/test_feature_generator_pipeline.py,sha256=CK0zVL8PfTncy3RmG9i-YpgwjOIV7yJhV7Q44tbetI8,19020
78
78
  tests/cross_validator/test_cross_validator.py,sha256=itCGhNY8-NbDbKbhxHW20wiLuRst7-Rixpmi3FSKQtA,17474
79
79
  tests/distributions/test_distribution.py,sha256=aU8hfCgliM80TES4WGjs9KFXpV8XghBGF7Hu9sqEVSE,10982
80
80
  tests/end_to_end/test_estimator_hyperparameter_tuning.py,sha256=fZCJ9rrED2vT68B9ovmVA1cIG2pHRTjy9xzZLxxpEBo,2513
@@ -92,7 +92,7 @@ tests/feature_generator/test_rolling_mean_days.py,sha256=EyOvdJDnmgPfe13uQBOkwo7
92
92
  tests/feature_generator/test_rolling_window.py,sha256=YBJo36OK3ILYeXrH06ylXqviUcCaGYaVQaK5RJzwM7Y,23239
93
93
  tests/hyperparameter_tuning/test_estimator_tuner.py,sha256=iewME41d6LR2aQ0OtohGFtN_ocJUwTeqvs6L0QDmfG4,4413
94
94
  tests/hyperparameter_tuning/test_rating_tuner.py,sha256=PyCFP3KPc4Iy9E_X9stCVxra14uMgC1tuRwuQ30rO_o,13195
95
- tests/performance_transformers/test_performance_manager.py,sha256=bfC5GiBuzHw-mLmKeEzBUUPuKm0ayax2bsF1j88W8L0,10120
95
+ tests/performance_transformers/test_performance_manager.py,sha256=gjuuV_hb27kCo_kUecPKG3Cbot2Gqis1W3kw2A4ovS4,10690
96
96
  tests/performance_transformers/test_performances_transformers.py,sha256=A-tGiCx7kXrj1cVj03Bc7prOeZ1_Ryz8YFx9uj3eK6w,11064
97
97
  tests/ratings/test_player_rating_generator.py,sha256=FGH3Tq0uFoSlkS_XMldsUKhsovBRBvzH9EbqjKvg2O0,59601
98
98
  tests/ratings/test_ratings_property.py,sha256=ckyfGILXa4tfQvsgyXEzBDNr2DUmHwFRV13N60w66iE,6561
@@ -105,7 +105,7 @@ tests/transformers/test_other_transformer.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRk
105
105
  tests/transformers/test_predictor_transformer.py,sha256=N1aBYLjN3ldpYZLwjih_gTFYSMitrZu-PNK78W6RHaQ,6877
106
106
  tests/transformers/test_simple_transformer.py,sha256=wWR0qjLb_uS4HXrJgGdiqugOY1X7kwd1_OPS02IT2b8,4676
107
107
  tests/transformers/test_team_ratio_predictor.py,sha256=fOUP_JvNJi-3kom3ZOs1EdG0I6Z8hpLpYKNHu1eWtOw,8562
108
- spforge-0.8.7.dist-info/METADATA,sha256=7vwprmmFvSpEL3lC0HqFZPbzxMi8mRzI0yOsa7pUlNQ,20047
109
- spforge-0.8.7.dist-info/WHEEL,sha256=qELbo2s1Yzl39ZmrAibXA2jjPLUYfnVhUNTlyF1rq0Y,92
110
- spforge-0.8.7.dist-info/top_level.txt,sha256=6UW2M5a7WKOeaAi900qQmRKNj5-HZzE8-eUD9Y9LTq0,23
111
- spforge-0.8.7.dist-info/RECORD,,
108
+ spforge-0.8.9.dist-info/METADATA,sha256=-HC4cuWjOzbV-SHZiopaJQ_WJv9Q2K_QNjjLj5gHohg,20047
109
+ spforge-0.8.9.dist-info/WHEEL,sha256=qELbo2s1Yzl39ZmrAibXA2jjPLUYfnVhUNTlyF1rq0Y,92
110
+ spforge-0.8.9.dist-info/top_level.txt,sha256=6UW2M5a7WKOeaAi900qQmRKNj5-HZzE8-eUD9Y9LTq0,23
111
+ spforge-0.8.9.dist-info/RECORD,,
@@ -56,6 +56,21 @@ def test_performance_weights_manager_basic_flow(sample_data):
56
56
  assert output_df["weighted_performance"].iloc[0] == pytest.approx(0.6)
57
57
 
58
58
 
59
+ def test_performance_weights_manager_keeps_mean_when_weights_not_normalized():
60
+ df = pd.DataFrame(
61
+ {
62
+ "feat_a": [0.0, 1.0, 2.0, 3.0],
63
+ "feat_b": [3.0, 2.0, 1.0, 0.0],
64
+ }
65
+ )
66
+ weights = [ColumnWeight(name="feat_a", weight=0.9), ColumnWeight(name="feat_b", weight=0.5)]
67
+
68
+ manager = PerformanceWeightsManager(weights=weights, transformer_names=["min_max"], prefix="")
69
+ output_df = nw.from_native(manager.fit_transform(df)).to_pandas()
70
+
71
+ assert output_df["weighted_performance"].mean() == pytest.approx(0.5, abs=1e-6)
72
+
73
+
59
74
  def test_lower_is_better_logic():
60
75
  df = pd.DataFrame({"feat_a": [1.0, 0.0]})
61
76
  weights = [ColumnWeight(name="feat_a", weight=1.0, lower_is_better=True)]
@@ -16,6 +16,49 @@ def column_names():
16
16
  )
17
17
 
18
18
 
19
+ class PolarsOnlyGenerator:
20
+ def __init__(self):
21
+ self._features_out = ["polars_only_feature"]
22
+
23
+ @property
24
+ def features_out(self):
25
+ return self._features_out
26
+
27
+ def fit_transform(self, df, column_names=None):
28
+ if not isinstance(df, pl.DataFrame):
29
+ raise TypeError("Expected polars DataFrame")
30
+ return df.with_columns((pl.col("points") * 2).alias("polars_only_feature"))
31
+
32
+ def transform(self, df):
33
+ if not isinstance(df, pl.DataFrame):
34
+ raise TypeError("Expected polars DataFrame")
35
+ return df.with_columns((pl.col("points") * 2).alias("polars_only_feature"))
36
+
37
+ def future_transform(self, df):
38
+ return self.transform(df)
39
+
40
+
41
+ def test_feature_generator_pipeline__passes_native_polars_to_custom_generator(column_names):
42
+ data = pl.DataFrame(
43
+ {
44
+ "game_id": [1, 1],
45
+ "team_id": ["A", "B"],
46
+ "player_id": ["p1", "p2"],
47
+ "date": pd.to_datetime(["2023-01-01", "2023-01-01"]),
48
+ "points": [10, 15],
49
+ }
50
+ )
51
+
52
+ pipeline = FeatureGeneratorPipeline(
53
+ feature_generators=[PolarsOnlyGenerator()],
54
+ column_names=column_names,
55
+ )
56
+
57
+ result = pipeline.fit_transform(data, column_names=column_names)
58
+
59
+ assert "polars_only_feature" in result.columns
60
+
61
+
19
62
  @pytest.mark.parametrize("df_type", [pd.DataFrame, pl.DataFrame])
20
63
  def test_feature_generator_pipeline__fit_transform_preserves_row_count(df_type, column_names):
21
64
  """FeatureGeneratorPipeline.fit_transform should preserve row count."""