Commit ae0a9c2
Migrate CategoricalMethodsMixin (encoding base) to narwhals, add polars support
Shared base for all 8 encoders. _get_feature_names_in() and
_check_transform_input_and_state() follow the same is_pandas-gated
column-reorder pattern as BaseImputer/DecisionTreeFeatures.
_check_or_select_variables() needed no change: the variable_handling
helpers it calls are already fully narwhals-generic.
The hot path is _encode()/inverse_transform(), a per-column
dict-based map applied on every transform() call across every
encoder. Benchmarked pandas-native .map(dict) vs narwhals
Series.replace_strict(dict, default=...) at 10k/50k/100k rows x
1/2/10 columns x 5/50 categories (warmed up first to remove
first-call JIT/import overhead): narwhals-on-pandas lands at
~1.06x-1.2x of pandas-native at realistic sizes (50k-100k rows),
i.e. minimal loss - merged into a single narwhals path per the
established decision rule, no pandas fast-path split. narwhals-on-
polars is consistently ~4-5x faster than pandas-native at 100k rows.
replace_strict() also *simplifies* the old logic: pandas' plain
.map() leaves category-dtype columns as category dtype after
mapping, which the old code corrected with a manual "cast to int
if all-int else float" step. Verified narwhals' replace_strict
resolves straight to a plain numeric dtype on both a pandas
category column and a polars Categorical column, so that dtype
fixup is dead code once replace_strict replaces .map() - dropped
it entirely rather than porting it.
Used Series.get_column().replace_strict() (not nw.col(), which
only accepts string names) throughout, same as DecisionTreeFeatures'
precedent for pandas integer column names - nw.col(feature) blew up
on int-named columns (caught by the existing
test_column_names_are_numbers test, which polars can't cover since
it has no integer-column-name concept).
_check_nan_values_after_transformation() rewritten off pandas'
.isnull().sum().sum()/.columns[...] chain onto per-column
Series.null_count(), for the same int-column-name reason.
Verified: tests/test_encoding full suite unchanged (17 pre-existing
failures - numpy-array-input rejection per the narwhals check_X()
contract, plus 3 MeanEncoder inverse_transform failures caused by a
pre-existing bug in mean_encoding.py's still-unmigrated fit() passing
a numpy y into y.groupby(); reproduced identically against the
unmodified base_encoder.py to confirm neither predates nor is
introduced by this change - 326 passed both before and after, same
failing test IDs). flake8 and mypy clean on the file. Module imports
with pandas blocked (loaded standalone, since sibling encoder files
in this package are not yet migrated and still import pandas at
their own module level). sphinx -W build clean (only the
pre-existing unrelated linkcode_resolve warning). Manually verified
CountEncoder end-to-end on polars input (fit still pandas-only until
its own migration, transform/inverse_transform now backend-agnostic
via this mixin) produces identical values to the pandas path,
including a pre-existing quirk where count-encoding inverse_transform
is ambiguous for categories that share a count (confirmed identical,
not a regression, on the old code too).
_helper_functions.py checked: pure-python parameter validation, no
dataframe interaction, no pandas import - left untouched.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>1 parent ed91d48 commit ae0a9c2
1 file changed
Lines changed: 69 additions & 46 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | 1 | | |
2 | 2 | | |
3 | 3 | | |
4 | | - | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
5 | 7 | | |
6 | 8 | | |
7 | 9 | | |
| |||
121 | 123 | | |
122 | 124 | | |
123 | 125 | | |
124 | | - | |
| 126 | + | |
125 | 127 | | |
126 | 128 | | |
127 | 129 | | |
128 | | - | |
| 130 | + | |
129 | 131 | | |
130 | 132 | | |
131 | 133 | | |
132 | 134 | | |
133 | 135 | | |
134 | 136 | | |
135 | 137 | | |
136 | | - | |
| 138 | + | |
137 | 139 | | |
138 | 140 | | |
139 | 141 | | |
| |||
159 | 161 | | |
160 | 162 | | |
161 | 163 | | |
162 | | - | |
| 164 | + | |
163 | 165 | | |
164 | 166 | | |
165 | 167 | | |
166 | 168 | | |
167 | 169 | | |
168 | | - | |
| 170 | + | |
| 171 | + | |
| 172 | + | |
| 173 | + | |
| 174 | + | |
169 | 175 | | |
170 | 176 | | |
171 | 177 | | |
172 | 178 | | |
173 | | - | |
| 179 | + | |
174 | 180 | | |
175 | 181 | | |
176 | 182 | | |
177 | 183 | | |
178 | 184 | | |
179 | 185 | | |
180 | | - | |
| 186 | + | |
181 | 187 | | |
182 | 188 | | |
183 | 189 | | |
184 | 190 | | |
185 | | - | |
| 191 | + | |
186 | 192 | | |
187 | 193 | | |
188 | 194 | | |
189 | 195 | | |
190 | 196 | | |
191 | 197 | | |
192 | | - | |
| 198 | + | |
193 | 199 | | |
194 | 200 | | |
195 | 201 | | |
| |||
203 | 209 | | |
204 | 210 | | |
205 | 211 | | |
206 | | - | |
| 212 | + | |
| 213 | + | |
| 214 | + | |
| 215 | + | |
| 216 | + | |
| 217 | + | |
| 218 | + | |
| 219 | + | |
| 220 | + | |
207 | 221 | | |
208 | 222 | | |
209 | 223 | | |
210 | | - | |
| 224 | + | |
211 | 225 | | |
212 | 226 | | |
213 | 227 | | |
214 | 228 | | |
215 | | - | |
| 229 | + | |
216 | 230 | | |
217 | 231 | | |
218 | 232 | | |
219 | 233 | | |
220 | | - | |
| 234 | + | |
221 | 235 | | |
222 | 236 | | |
223 | 237 | | |
| |||
231 | 245 | | |
232 | 246 | | |
233 | 247 | | |
234 | | - | |
235 | | - | |
236 | | - | |
237 | | - | |
238 | | - | |
239 | | - | |
240 | | - | |
241 | | - | |
242 | | - | |
243 | | - | |
244 | | - | |
245 | | - | |
246 | | - | |
247 | | - | |
248 | | - | |
249 | | - | |
| 248 | + | |
| 249 | + | |
| 250 | + | |
| 251 | + | |
| 252 | + | |
| 253 | + | |
| 254 | + | |
| 255 | + | |
| 256 | + | |
| 257 | + | |
| 258 | + | |
| 259 | + | |
| 260 | + | |
| 261 | + | |
| 262 | + | |
| 263 | + | |
| 264 | + | |
| 265 | + | |
| 266 | + | |
250 | 267 | | |
251 | 268 | | |
252 | 269 | | |
| |||
255 | 272 | | |
256 | 273 | | |
257 | 274 | | |
258 | | - | |
| 275 | + | |
| 276 | + | |
| 277 | + | |
| 278 | + | |
| 279 | + | |
| 280 | + | |
259 | 281 | | |
260 | | - | |
261 | | - | |
262 | | - | |
263 | | - | |
264 | | - | |
265 | | - | |
| 282 | + | |
266 | 283 | | |
267 | 284 | | |
268 | | - | |
| 285 | + | |
269 | 286 | | |
270 | | - | |
| 287 | + | |
271 | 288 | | |
272 | 289 | | |
273 | 290 | | |
| |||
280 | 297 | | |
281 | 298 | | |
282 | 299 | | |
283 | | - | |
| 300 | + | |
284 | 301 | | |
285 | 302 | | |
286 | 303 | | |
287 | 304 | | |
288 | | - | |
| 305 | + | |
289 | 306 | | |
290 | 307 | | |
291 | 308 | | |
292 | 309 | | |
293 | | - | |
| 310 | + | |
294 | 311 | | |
295 | 312 | | |
296 | 313 | | |
297 | 314 | | |
298 | 315 | | |
299 | 316 | | |
300 | | - | |
301 | | - | |
302 | | - | |
303 | | - | |
| 317 | + | |
| 318 | + | |
| 319 | + | |
| 320 | + | |
| 321 | + | |
| 322 | + | |
| 323 | + | |
| 324 | + | |
| 325 | + | |
| 326 | + | |
304 | 327 | | |
305 | 328 | | |
306 | 329 | | |
| |||
0 commit comments