spforge 0.8.13__tar.gz → 0.8.14__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.

Potentially problematic release.


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

Files changed (119) hide show
  1. {spforge-0.8.13/spforge.egg-info → spforge-0.8.14}/PKG-INFO +1 -1
  2. {spforge-0.8.13 → spforge-0.8.14}/pyproject.toml +1 -1
  3. {spforge-0.8.13 → spforge-0.8.14}/spforge/autopipeline.py +46 -0
  4. {spforge-0.8.13 → spforge-0.8.14/spforge.egg-info}/PKG-INFO +1 -1
  5. {spforge-0.8.13 → spforge-0.8.14}/tests/test_autopipeline.py +31 -0
  6. {spforge-0.8.13 → spforge-0.8.14}/LICENSE +0 -0
  7. {spforge-0.8.13 → spforge-0.8.14}/MANIFEST.in +0 -0
  8. {spforge-0.8.13 → spforge-0.8.14}/README.md +0 -0
  9. {spforge-0.8.13 → spforge-0.8.14}/examples/__init__.py +0 -0
  10. {spforge-0.8.13 → spforge-0.8.14}/examples/game_level_example.py +0 -0
  11. {spforge-0.8.13 → spforge-0.8.14}/examples/lol/__init__.py +0 -0
  12. {spforge-0.8.13 → spforge-0.8.14}/examples/lol/data/__init__.py +0 -0
  13. {spforge-0.8.13 → spforge-0.8.14}/examples/lol/data/subsample_lol_data.parquet +0 -0
  14. {spforge-0.8.13 → spforge-0.8.14}/examples/lol/data/utils.py +0 -0
  15. {spforge-0.8.13 → spforge-0.8.14}/examples/lol/pipeline_transformer_example.py +0 -0
  16. {spforge-0.8.13 → spforge-0.8.14}/examples/nba/__init__.py +0 -0
  17. {spforge-0.8.13 → spforge-0.8.14}/examples/nba/cross_validation_example.py +0 -0
  18. {spforge-0.8.13 → spforge-0.8.14}/examples/nba/data/__init__.py +0 -0
  19. {spforge-0.8.13 → spforge-0.8.14}/examples/nba/data/game_player_subsample.parquet +0 -0
  20. {spforge-0.8.13 → spforge-0.8.14}/examples/nba/data/utils.py +0 -0
  21. {spforge-0.8.13 → spforge-0.8.14}/examples/nba/feature_engineering_example.py +0 -0
  22. {spforge-0.8.13 → spforge-0.8.14}/examples/nba/game_winner_example.py +0 -0
  23. {spforge-0.8.13 → spforge-0.8.14}/examples/nba/predictor_transformers_example.py +0 -0
  24. {spforge-0.8.13 → spforge-0.8.14}/setup.cfg +0 -0
  25. {spforge-0.8.13 → spforge-0.8.14}/spforge/__init__.py +0 -0
  26. {spforge-0.8.13 → spforge-0.8.14}/spforge/base_feature_generator.py +0 -0
  27. {spforge-0.8.13 → spforge-0.8.14}/spforge/cross_validator/__init__.py +0 -0
  28. {spforge-0.8.13 → spforge-0.8.14}/spforge/cross_validator/_base.py +0 -0
  29. {spforge-0.8.13 → spforge-0.8.14}/spforge/cross_validator/cross_validator.py +0 -0
  30. {spforge-0.8.13 → spforge-0.8.14}/spforge/data_structures.py +0 -0
  31. {spforge-0.8.13 → spforge-0.8.14}/spforge/distributions/__init__.py +0 -0
  32. {spforge-0.8.13 → spforge-0.8.14}/spforge/distributions/_negative_binomial_estimator.py +0 -0
  33. {spforge-0.8.13 → spforge-0.8.14}/spforge/distributions/_normal_distribution_predictor.py +0 -0
  34. {spforge-0.8.13 → spforge-0.8.14}/spforge/distributions/_student_t_distribution_estimator.py +0 -0
  35. {spforge-0.8.13 → spforge-0.8.14}/spforge/estimator/__init__.py +0 -0
  36. {spforge-0.8.13 → spforge-0.8.14}/spforge/estimator/_conditional_estimator.py +0 -0
  37. {spforge-0.8.13 → spforge-0.8.14}/spforge/estimator/_frequency_bucketing_classifier.py +0 -0
  38. {spforge-0.8.13 → spforge-0.8.14}/spforge/estimator/_granularity_estimator.py +0 -0
  39. {spforge-0.8.13 → spforge-0.8.14}/spforge/estimator/_group_by_estimator.py +0 -0
  40. {spforge-0.8.13 → spforge-0.8.14}/spforge/estimator/_ordinal_classifier.py +0 -0
  41. {spforge-0.8.13 → spforge-0.8.14}/spforge/estimator/_sklearn_enhancer_estimator.py +0 -0
  42. {spforge-0.8.13 → spforge-0.8.14}/spforge/feature_generator/__init__.py +0 -0
  43. {spforge-0.8.13 → spforge-0.8.14}/spforge/feature_generator/_base.py +0 -0
  44. {spforge-0.8.13 → spforge-0.8.14}/spforge/feature_generator/_lag.py +0 -0
  45. {spforge-0.8.13 → spforge-0.8.14}/spforge/feature_generator/_net_over_predicted.py +0 -0
  46. {spforge-0.8.13 → spforge-0.8.14}/spforge/feature_generator/_regressor_feature_generator.py +0 -0
  47. {spforge-0.8.13 → spforge-0.8.14}/spforge/feature_generator/_rolling_against_opponent.py +0 -0
  48. {spforge-0.8.13 → spforge-0.8.14}/spforge/feature_generator/_rolling_mean_binary.py +0 -0
  49. {spforge-0.8.13 → spforge-0.8.14}/spforge/feature_generator/_rolling_mean_days.py +0 -0
  50. {spforge-0.8.13 → spforge-0.8.14}/spforge/feature_generator/_rolling_window.py +0 -0
  51. {spforge-0.8.13 → spforge-0.8.14}/spforge/feature_generator/_utils.py +0 -0
  52. {spforge-0.8.13 → spforge-0.8.14}/spforge/features_generator_pipeline.py +0 -0
  53. {spforge-0.8.13 → spforge-0.8.14}/spforge/hyperparameter_tuning/__init__.py +0 -0
  54. {spforge-0.8.13 → spforge-0.8.14}/spforge/hyperparameter_tuning/_default_search_spaces.py +0 -0
  55. {spforge-0.8.13 → spforge-0.8.14}/spforge/hyperparameter_tuning/_tuner.py +0 -0
  56. {spforge-0.8.13 → spforge-0.8.14}/spforge/performance_transformers/__init__.py +0 -0
  57. {spforge-0.8.13 → spforge-0.8.14}/spforge/performance_transformers/_performance_manager.py +0 -0
  58. {spforge-0.8.13 → spforge-0.8.14}/spforge/performance_transformers/_performances_transformers.py +0 -0
  59. {spforge-0.8.13 → spforge-0.8.14}/spforge/ratings/__init__.py +0 -0
  60. {spforge-0.8.13 → spforge-0.8.14}/spforge/ratings/_base.py +0 -0
  61. {spforge-0.8.13 → spforge-0.8.14}/spforge/ratings/_player_rating.py +0 -0
  62. {spforge-0.8.13 → spforge-0.8.14}/spforge/ratings/_team_rating.py +0 -0
  63. {spforge-0.8.13 → spforge-0.8.14}/spforge/ratings/enums.py +0 -0
  64. {spforge-0.8.13 → spforge-0.8.14}/spforge/ratings/league_identifier.py +0 -0
  65. {spforge-0.8.13 → spforge-0.8.14}/spforge/ratings/league_start_rating_optimizer.py +0 -0
  66. {spforge-0.8.13 → spforge-0.8.14}/spforge/ratings/player_performance_predictor.py +0 -0
  67. {spforge-0.8.13 → spforge-0.8.14}/spforge/ratings/start_rating_generator.py +0 -0
  68. {spforge-0.8.13 → spforge-0.8.14}/spforge/ratings/team_performance_predictor.py +0 -0
  69. {spforge-0.8.13 → spforge-0.8.14}/spforge/ratings/team_start_rating_generator.py +0 -0
  70. {spforge-0.8.13 → spforge-0.8.14}/spforge/ratings/utils.py +0 -0
  71. {spforge-0.8.13 → spforge-0.8.14}/spforge/scorer/__init__.py +0 -0
  72. {spforge-0.8.13 → spforge-0.8.14}/spforge/scorer/_score.py +0 -0
  73. {spforge-0.8.13 → spforge-0.8.14}/spforge/transformers/__init__.py +0 -0
  74. {spforge-0.8.13 → spforge-0.8.14}/spforge/transformers/_base.py +0 -0
  75. {spforge-0.8.13 → spforge-0.8.14}/spforge/transformers/_net_over_predicted.py +0 -0
  76. {spforge-0.8.13 → spforge-0.8.14}/spforge/transformers/_operator.py +0 -0
  77. {spforge-0.8.13 → spforge-0.8.14}/spforge/transformers/_other_transformer.py +0 -0
  78. {spforge-0.8.13 → spforge-0.8.14}/spforge/transformers/_predictor.py +0 -0
  79. {spforge-0.8.13 → spforge-0.8.14}/spforge/transformers/_simple_transformer.py +0 -0
  80. {spforge-0.8.13 → spforge-0.8.14}/spforge/transformers/_team_ratio_predictor.py +0 -0
  81. {spforge-0.8.13 → spforge-0.8.14}/spforge/utils.py +0 -0
  82. {spforge-0.8.13 → spforge-0.8.14}/spforge.egg-info/SOURCES.txt +0 -0
  83. {spforge-0.8.13 → spforge-0.8.14}/spforge.egg-info/dependency_links.txt +0 -0
  84. {spforge-0.8.13 → spforge-0.8.14}/spforge.egg-info/requires.txt +0 -0
  85. {spforge-0.8.13 → spforge-0.8.14}/spforge.egg-info/top_level.txt +0 -0
  86. {spforge-0.8.13 → spforge-0.8.14}/tests/cross_validator/test_cross_validator.py +0 -0
  87. {spforge-0.8.13 → spforge-0.8.14}/tests/distributions/test_distribution.py +0 -0
  88. {spforge-0.8.13 → spforge-0.8.14}/tests/end_to_end/test_estimator_hyperparameter_tuning.py +0 -0
  89. {spforge-0.8.13 → spforge-0.8.14}/tests/end_to_end/test_league_start_rating_optimizer.py +0 -0
  90. {spforge-0.8.13 → spforge-0.8.14}/tests/end_to_end/test_lol_player_kills.py +0 -0
  91. {spforge-0.8.13 → spforge-0.8.14}/tests/end_to_end/test_nba_player_points.py +0 -0
  92. {spforge-0.8.13 → spforge-0.8.14}/tests/end_to_end/test_nba_player_ratings_hyperparameter_tuning.py +0 -0
  93. {spforge-0.8.13 → spforge-0.8.14}/tests/end_to_end/test_nba_prediction_consistency.py +0 -0
  94. {spforge-0.8.13 → spforge-0.8.14}/tests/estimator/test_sklearn_estimator.py +0 -0
  95. {spforge-0.8.13 → spforge-0.8.14}/tests/feature_generator/test_lag.py +0 -0
  96. {spforge-0.8.13 → spforge-0.8.14}/tests/feature_generator/test_regressor_feature_generator.py +0 -0
  97. {spforge-0.8.13 → spforge-0.8.14}/tests/feature_generator/test_rolling_against_opponent.py +0 -0
  98. {spforge-0.8.13 → spforge-0.8.14}/tests/feature_generator/test_rolling_mean_binary.py +0 -0
  99. {spforge-0.8.13 → spforge-0.8.14}/tests/feature_generator/test_rolling_mean_days.py +0 -0
  100. {spforge-0.8.13 → spforge-0.8.14}/tests/feature_generator/test_rolling_window.py +0 -0
  101. {spforge-0.8.13 → spforge-0.8.14}/tests/hyperparameter_tuning/test_estimator_tuner.py +0 -0
  102. {spforge-0.8.13 → spforge-0.8.14}/tests/hyperparameter_tuning/test_rating_tuner.py +0 -0
  103. {spforge-0.8.13 → spforge-0.8.14}/tests/performance_transformers/test_performance_manager.py +0 -0
  104. {spforge-0.8.13 → spforge-0.8.14}/tests/performance_transformers/test_performances_transformers.py +0 -0
  105. {spforge-0.8.13 → spforge-0.8.14}/tests/ratings/test_player_rating_generator.py +0 -0
  106. {spforge-0.8.13 → spforge-0.8.14}/tests/ratings/test_player_rating_no_mutation.py +0 -0
  107. {spforge-0.8.13 → spforge-0.8.14}/tests/ratings/test_ratings_property.py +0 -0
  108. {spforge-0.8.13 → spforge-0.8.14}/tests/ratings/test_team_rating_generator.py +0 -0
  109. {spforge-0.8.13 → spforge-0.8.14}/tests/ratings/test_utils_scaled_weights.py +0 -0
  110. {spforge-0.8.13 → spforge-0.8.14}/tests/scorer/test_score.py +0 -0
  111. {spforge-0.8.13 → spforge-0.8.14}/tests/scorer/test_score_aggregation_granularity.py +0 -0
  112. {spforge-0.8.13 → spforge-0.8.14}/tests/test_autopipeline_context.py +0 -0
  113. {spforge-0.8.13 → spforge-0.8.14}/tests/test_feature_generator_pipeline.py +0 -0
  114. {spforge-0.8.13 → spforge-0.8.14}/tests/transformers/test_estimator_transformer_context.py +0 -0
  115. {spforge-0.8.13 → spforge-0.8.14}/tests/transformers/test_net_over_predicted.py +0 -0
  116. {spforge-0.8.13 → spforge-0.8.14}/tests/transformers/test_other_transformer.py +0 -0
  117. {spforge-0.8.13 → spforge-0.8.14}/tests/transformers/test_predictor_transformer.py +0 -0
  118. {spforge-0.8.13 → spforge-0.8.14}/tests/transformers/test_simple_transformer.py +0 -0
  119. {spforge-0.8.13 → spforge-0.8.14}/tests/transformers/test_team_ratio_predictor.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: spforge
3
- Version: 0.8.13
3
+ Version: 0.8.14
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
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "spforge"
7
- version = "0.8.13"
7
+ version = "0.8.14"
8
8
  description = "A flexible framework for generating features, ratings, and building machine learning or other models for training and inference on sports data."
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.11"
@@ -681,6 +681,22 @@ class AutoPipeline(BaseEstimator):
681
681
 
682
682
  return features
683
683
 
684
+ def _resolve_importance_feature_names(self, estimator, n_features: int) -> list[str]:
685
+ names = None
686
+ if hasattr(estimator, "feature_names_in_") and estimator.feature_names_in_ is not None:
687
+ names = list(estimator.feature_names_in_)
688
+ elif hasattr(estimator, "feature_name_") and estimator.feature_name_ is not None:
689
+ names = list(estimator.feature_name_)
690
+ elif hasattr(estimator, "feature_names_") and estimator.feature_names_ is not None:
691
+ names = list(estimator.feature_names_)
692
+ if names is None:
693
+ names = self._get_estimator_feature_names()
694
+ if len(names) != n_features:
695
+ raise ValueError(
696
+ f"Feature names length ({len(names)}) does not match importances length ({n_features})."
697
+ )
698
+ return names
699
+
684
700
  @property
685
701
  def feature_importances_(self) -> pd.DataFrame:
686
702
  """Get feature importances from the fitted estimator.
@@ -719,3 +735,33 @@ class AutoPipeline(BaseEstimator):
719
735
  df = pd.DataFrame({"feature": feature_names, "importance": importances})
720
736
  df = df.sort_values("importance", ascending=False, key=abs).reset_index(drop=True)
721
737
  return df
738
+
739
+ @property
740
+ def feature_importance_names(self) -> dict[str, float]:
741
+ """Map deepest estimator feature names to importances."""
742
+ if self.sklearn_pipeline is None:
743
+ raise RuntimeError("Pipeline not fitted. Call fit() first.")
744
+
745
+ est = self.sklearn_pipeline.named_steps["est"]
746
+ result = _get_importance_estimator(est)
747
+
748
+ if result is None:
749
+ raise RuntimeError(
750
+ "Estimator does not support feature importances. "
751
+ "Requires feature_importances_ or coef_ attribute."
752
+ )
753
+
754
+ inner_est, attr_name = result
755
+ raw = getattr(inner_est, attr_name)
756
+
757
+ if attr_name == "coef_":
758
+ if raw.ndim == 2:
759
+ importances = np.abs(raw).mean(axis=0)
760
+ else:
761
+ importances = np.abs(raw)
762
+ else:
763
+ importances = raw
764
+
765
+ importances = np.asarray(importances)
766
+ feature_names = self._resolve_importance_feature_names(inner_est, len(importances))
767
+ return dict(zip(feature_names, importances.tolist()))
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: spforge
3
- Version: 0.8.13
3
+ Version: 0.8.14
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
@@ -692,3 +692,34 @@ def test_feature_importances__onehot_features():
692
692
  assert len(importances) == 4
693
693
  assert "num1" in importances["feature"].tolist()
694
694
  assert any("cat1_" in f for f in importances["feature"].tolist())
695
+
696
+
697
+ def test_feature_importance_names__granularity_uses_deep_feature_names():
698
+ from sklearn.ensemble import RandomForestRegressor
699
+
700
+ df = pd.DataFrame(
701
+ {
702
+ "gameid": ["g1", "g1", "g2", "g2"],
703
+ "num1": [1.0, 2.0, 3.0, 4.0],
704
+ "num2": [10.0, 20.0, 30.0, 40.0],
705
+ }
706
+ )
707
+ y = pd.Series([1.0, 2.0, 3.0, 4.0], name="y")
708
+
709
+ model = AutoPipeline(
710
+ estimator=RandomForestRegressor(n_estimators=5, random_state=42),
711
+ estimator_features=["gameid", "num1", "num2"],
712
+ predictor_transformers=[AddConstantPredictionTransformer(col_name="const_pred")],
713
+ granularity=["gameid"],
714
+ categorical_features=["gameid"],
715
+ categorical_handling="ordinal",
716
+ remainder="drop",
717
+ )
718
+ model.fit(df, y)
719
+
720
+ names = model.feature_importance_names
721
+
722
+ inner = _inner_estimator(model)
723
+ assert list(names.keys()) == list(inner.feature_names_in_)
724
+ assert "gameid" not in names
725
+ assert "const_pred" in names
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes