gitlabds 2.1.10__tar.gz → 2.1.11__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 (25) hide show
  1. {gitlabds-2.1.10 → gitlabds-2.1.11}/PKG-INFO +1 -1
  2. {gitlabds-2.1.10 → gitlabds-2.1.11}/gitlabds/model_evaluator.py +93 -10
  3. {gitlabds-2.1.10 → gitlabds-2.1.11}/gitlabds.egg-info/PKG-INFO +1 -1
  4. {gitlabds-2.1.10 → gitlabds-2.1.11}/LICENSE +0 -0
  5. {gitlabds-2.1.10 → gitlabds-2.1.11}/README.md +0 -0
  6. {gitlabds-2.1.10 → gitlabds-2.1.11}/gitlabds/__init__.py +0 -0
  7. {gitlabds-2.1.10 → gitlabds-2.1.11}/gitlabds/baselines.py +0 -0
  8. {gitlabds-2.1.10 → gitlabds-2.1.11}/gitlabds/config_generator.py +0 -0
  9. {gitlabds-2.1.10 → gitlabds-2.1.11}/gitlabds/dummy.py +0 -0
  10. {gitlabds-2.1.10 → gitlabds-2.1.11}/gitlabds/feature_reduction.py +0 -0
  11. {gitlabds-2.1.10 → gitlabds-2.1.11}/gitlabds/insights.py +0 -0
  12. {gitlabds-2.1.10 → gitlabds-2.1.11}/gitlabds/memory_optimization.py +0 -0
  13. {gitlabds-2.1.10 → gitlabds-2.1.11}/gitlabds/missing.py +0 -0
  14. {gitlabds-2.1.10 → gitlabds-2.1.11}/gitlabds/monitoring_metrics.py +0 -0
  15. {gitlabds-2.1.10 → gitlabds-2.1.11}/gitlabds/outliers.py +0 -0
  16. {gitlabds-2.1.10 → gitlabds-2.1.11}/gitlabds/serving_features.py +0 -0
  17. {gitlabds-2.1.10 → gitlabds-2.1.11}/gitlabds/split_data.py +0 -0
  18. {gitlabds-2.1.10 → gitlabds-2.1.11}/gitlabds/trends.py +0 -0
  19. {gitlabds-2.1.10 → gitlabds-2.1.11}/gitlabds.egg-info/SOURCES.txt +0 -0
  20. {gitlabds-2.1.10 → gitlabds-2.1.11}/gitlabds.egg-info/dependency_links.txt +0 -0
  21. {gitlabds-2.1.10 → gitlabds-2.1.11}/gitlabds.egg-info/requires.txt +0 -0
  22. {gitlabds-2.1.10 → gitlabds-2.1.11}/gitlabds.egg-info/top_level.txt +0 -0
  23. {gitlabds-2.1.10 → gitlabds-2.1.11}/pyproject.toml +0 -0
  24. {gitlabds-2.1.10 → gitlabds-2.1.11}/setup.cfg +0 -0
  25. {gitlabds-2.1.10 → gitlabds-2.1.11}/setup.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: gitlabds
3
- Version: 2.1.10
3
+ Version: 2.1.11
4
4
  Summary: GitLab Data Science Tools
5
5
  Author-email: Kevin Dietz <kdietz@gitlab.com>
6
6
  License-Expression: MIT
@@ -2044,6 +2044,70 @@ class ModelEvaluator:
2044
2044
  ax.set_yticks([])
2045
2045
  ax.set_title(f"Class {class_idx}")
2046
2046
 
2047
+ def _expand_categorical_shap(self, shap_values, X):
2048
+ """
2049
+ Expand each categorical column's single SHAP column into one binary-
2050
+ indicator column per level (e.g. ``industry_prev`` -> ``industry_prev=Manufacturing``,
2051
+ ``industry_prev=Tech``, ...).
2052
+
2053
+ For each row, the per-level SHAP value equals the original column's SHAP
2054
+ value when the row had that level, otherwise 0. The feature value is a
2055
+ binary indicator (1 if the row has that level, else 0). This lets the
2056
+ beeswarm color gradient (red/blue) carry direction-of-effect information
2057
+ per level rather than collapsing every row to a single gray dot when
2058
+ native categorical handling (``enable_categorical=True``) is used.
2059
+
2060
+ Works with both 2D (binary classification / regression) and 3D
2061
+ (multiclass) SHAP value arrays. Non-categorical columns pass through
2062
+ untouched. If no categorical columns are detected, the input is returned
2063
+ unchanged.
2064
+ """
2065
+ try:
2066
+ import shap
2067
+ except ImportError:
2068
+ return shap_values
2069
+
2070
+ cat_cols = [c for c in X.columns if isinstance(X[c].dtype, pd.CategoricalDtype)]
2071
+ if not cat_cols:
2072
+ return shap_values
2073
+
2074
+ feature_names = list(X.columns)
2075
+ values = shap_values.values
2076
+ is_3d = values.ndim == 3
2077
+
2078
+ new_feature_names = []
2079
+ new_value_cols = []
2080
+ new_data_cols = []
2081
+
2082
+ for j, col in enumerate(feature_names):
2083
+ col_shap = values[:, j, :] if is_3d else values[:, j]
2084
+ if col in cat_cols:
2085
+ col_raw = X[col].astype(object).values
2086
+ # Stable, sorted level ordering for reproducibility
2087
+ levels = sorted([lv for lv in pd.unique(X[col]) if pd.notna(lv)],
2088
+ key=lambda v: str(v))
2089
+ for level in levels:
2090
+ mask = (col_raw == level)
2091
+ if is_3d:
2092
+ masked = np.where(mask[:, None], col_shap, 0.0)
2093
+ else:
2094
+ masked = np.where(mask, col_shap, 0.0)
2095
+ new_value_cols.append(masked)
2096
+ new_data_cols.append(mask.astype(float))
2097
+ new_feature_names.append(f"{col}={level}")
2098
+ else:
2099
+ new_value_cols.append(col_shap)
2100
+ new_data_cols.append(X[col].values)
2101
+ new_feature_names.append(col)
2102
+
2103
+ new_values = np.stack(new_value_cols, axis=1)
2104
+ new_data = np.stack(new_data_cols, axis=1)
2105
+
2106
+ kwargs = dict(values=new_values, data=new_data, feature_names=new_feature_names)
2107
+ if hasattr(shap_values, "base_values") and shap_values.base_values is not None:
2108
+ kwargs["base_values"] = shap_values.base_values
2109
+ return shap.Explanation(**kwargs)
2110
+
2047
2111
  def plot_shap_beeswarm(
2048
2112
  self,
2049
2113
  n_features: int = 20,
@@ -2055,17 +2119,29 @@ class ModelEvaluator:
2055
2119
  plot_name: str = "shap_beeswarm",
2056
2120
  plot_save_format: str = None,
2057
2121
  plot_save_dpi: str = None,
2058
- show_plot: bool = None
2122
+ show_plot: bool = None,
2123
+ expand_categoricals: bool = True,
2059
2124
  ) -> None:
2060
2125
  """
2061
2126
  Create a SHAP beeswarm plot for feature importance.
2062
-
2127
+
2063
2128
  Parameters
2064
2129
  ----------
2065
2130
  class_index : int, optional
2066
2131
  For multi-class classification, specify which class to plot.
2067
2132
  If None, plots global importance (averaged across classes).
2068
2133
  Only applicable for multi-class models.
2134
+ expand_categoricals : bool, default True
2135
+ If True, each categorical column (pandas ``category`` dtype) is split
2136
+ into per-level binary-indicator pseudo-features (e.g.
2137
+ ``industry_prev=Manufacturing``) before plotting. This lets the
2138
+ red/blue color gradient encode direction-of-effect per level when
2139
+ using native categorical handling (``enable_categorical=True``)
2140
+ instead of showing a single gray-dot row per categorical feature.
2141
+ The ``n_features`` (max_display) cap then ranks numerical features
2142
+ and per-level indicators on the same mean-|SHAP| scale, so only the
2143
+ impactful levels surface. Set False to preserve the original
2144
+ behavior.
2069
2145
  """
2070
2146
  # Set defaults if not provided
2071
2147
  save_plot = self.save_plots if save_plot is None else save_plot
@@ -2094,10 +2170,17 @@ class ModelEvaluator:
2094
2170
  try:
2095
2171
  # Create an explainer
2096
2172
  explainer = shap.Explainer(self.model)
2097
-
2173
+
2098
2174
  # Get SHAP values
2099
2175
  shap_values = explainer(X)
2100
-
2176
+
2177
+ # Expand categorical columns into per-level binary indicators so
2178
+ # the beeswarm color gradient encodes direction-of-effect per level
2179
+ # (e.g. industry_prev=Manufacturing red dots vs blue dots) rather
2180
+ # than collapsing each categorical feature to a single gray-dot row.
2181
+ if expand_categoricals:
2182
+ shap_values = self._expand_categorical_shap(shap_values, X)
2183
+
2101
2184
  # For multi-class classification
2102
2185
  if self.classification and self.n_classes > 2:
2103
2186
  if hasattr(shap_values, 'values') and len(shap_values.values.shape) == 3:
@@ -2112,8 +2195,8 @@ class ModelEvaluator:
2112
2195
  class_values = shap_values.values[:, :, class_index]
2113
2196
  class_exp = shap.Explanation(
2114
2197
  values=class_values,
2115
- data=X.values,
2116
- feature_names=X.columns.tolist()
2198
+ data=shap_values.data,
2199
+ feature_names=shap_values.feature_names,
2117
2200
  )
2118
2201
 
2119
2202
  # Create a figure first
@@ -2132,8 +2215,8 @@ class ModelEvaluator:
2132
2215
  global_values = shap_values.values.mean(axis=2)
2133
2216
  global_exp = shap.Explanation(
2134
2217
  values=global_values,
2135
- data=X.values,
2136
- feature_names=X.columns.tolist()
2218
+ data=shap_values.data,
2219
+ feature_names=shap_values.feature_names,
2137
2220
  )
2138
2221
 
2139
2222
  # Create a figure first
@@ -2489,8 +2572,8 @@ class ModelEvaluator:
2489
2572
  # Colored scatter plot
2490
2573
  # If specific pairs not provided, use top correlation pairs
2491
2574
  if feature_pairs is None:
2492
- # Calculate correlation matrix
2493
- corr_matrix = self.x_train.corr().abs()
2575
+ # Calculate correlation matrix (skip categoricals — corr is undefined for them)
2576
+ corr_matrix = self.x_train.corr(numeric_only=True).abs()
2494
2577
 
2495
2578
  # Set diagonal to 0
2496
2579
  np.fill_diagonal(corr_matrix.values, 0)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: gitlabds
3
- Version: 2.1.10
3
+ Version: 2.1.11
4
4
  Summary: GitLab Data Science Tools
5
5
  Author-email: Kevin Dietz <kdietz@gitlab.com>
6
6
  License-Expression: MIT
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes