@@ -317,7 +317,6 @@ def pandas_feature_info(
317
317
) -> Tuple [Optional [FeatureNames ], Optional [FeatureTypes ]]:
318
318
"""Handle feature info for pandas dataframe."""
319
319
import pandas as pd
320
- from pandas .api .types import is_categorical_dtype , is_sparse
321
320
322
321
# handle feature names
323
322
if feature_names is None and meta is None :
@@ -332,10 +331,10 @@ def pandas_feature_info(
332
331
if feature_types is None and meta is None :
333
332
feature_types = []
334
333
for dtype in data .dtypes :
335
- if is_sparse (dtype ):
334
+ if is_pd_sparse_dtype (dtype ):
336
335
feature_types .append (_pandas_dtype_mapper [dtype .subtype .name ])
337
336
elif (
338
- is_categorical_dtype (dtype ) or is_pa_ext_categorical_dtype (dtype )
337
+ is_pd_cat_dtype (dtype ) or is_pa_ext_categorical_dtype (dtype )
339
338
) and enable_categorical :
340
339
feature_types .append (CAT_T )
341
340
else :
@@ -345,18 +344,13 @@ def pandas_feature_info(
345
344
346
345
def is_nullable_dtype (dtype : PandasDType ) -> bool :
347
346
"""Whether dtype is a pandas nullable type."""
348
- from pandas .api .types import (
349
- is_bool_dtype ,
350
- is_categorical_dtype ,
351
- is_float_dtype ,
352
- is_integer_dtype ,
353
- )
347
+ from pandas .api .types import is_bool_dtype , is_float_dtype , is_integer_dtype
354
348
355
349
is_int = is_integer_dtype (dtype ) and dtype .name in pandas_nullable_mapper
356
350
# np.bool has alias `bool`, while pd.BooleanDtype has `boolean`.
357
351
is_bool = is_bool_dtype (dtype ) and dtype .name == "boolean"
358
352
is_float = is_float_dtype (dtype ) and dtype .name in pandas_nullable_mapper
359
- return is_int or is_bool or is_float or is_categorical_dtype (dtype )
353
+ return is_int or is_bool or is_float or is_pd_cat_dtype (dtype )
360
354
361
355
362
356
def is_pa_ext_dtype (dtype : Any ) -> bool :
@@ -371,17 +365,48 @@ def is_pa_ext_categorical_dtype(dtype: Any) -> bool:
371
365
)
372
366
373
367
368
+ def is_pd_cat_dtype (dtype : PandasDType ) -> bool :
369
+ """Wrapper for testing pandas category type."""
370
+ import pandas as pd
371
+
372
+ if hasattr (pd .util , "version" ) and hasattr (pd .util .version , "Version" ):
373
+ Version = pd .util .version .Version
374
+ if Version (pd .__version__ ) >= Version ("2.1.0" ):
375
+ from pandas import CategoricalDtype
376
+
377
+ return isinstance (dtype , CategoricalDtype )
378
+
379
+ from pandas .api .types import is_categorical_dtype
380
+
381
+ return is_categorical_dtype (dtype )
382
+
383
+
384
+ def is_pd_sparse_dtype (dtype : PandasDType ) -> bool :
385
+ """Wrapper for testing pandas sparse type."""
386
+ import pandas as pd
387
+
388
+ if hasattr (pd .util , "version" ) and hasattr (pd .util .version , "Version" ):
389
+ Version = pd .util .version .Version
390
+ if Version (pd .__version__ ) >= Version ("2.1.0" ):
391
+ from pandas import SparseDtype
392
+
393
+ return isinstance (dtype , SparseDtype )
394
+
395
+ from pandas .api .types import is_sparse
396
+
397
+ return is_sparse (dtype )
398
+
399
+
374
400
def pandas_cat_null (data : DataFrame ) -> DataFrame :
375
401
"""Handle categorical dtype and nullable extension types from pandas."""
376
402
import pandas as pd
377
- from pandas .api .types import is_categorical_dtype
378
403
379
404
# handle category codes and nullable.
380
405
cat_columns = []
381
406
nul_columns = []
382
407
# avoid an unnecessary conversion if possible
383
408
for col , dtype in zip (data .columns , data .dtypes ):
384
- if is_categorical_dtype (dtype ):
409
+ if is_pd_cat_dtype (dtype ):
385
410
cat_columns .append (col )
386
411
elif is_pa_ext_categorical_dtype (dtype ):
387
412
raise ValueError (
@@ -398,7 +423,7 @@ def pandas_cat_null(data: DataFrame) -> DataFrame:
398
423
transformed = data
399
424
400
425
def cat_codes (ser : pd .Series ) -> pd .Series :
401
- if is_categorical_dtype (ser .dtype ):
426
+ if is_pd_cat_dtype (ser .dtype ):
402
427
return ser .cat .codes
403
428
assert is_pa_ext_categorical_dtype (ser .dtype )
404
429
# Not yet supported, the index is not ordered for some reason. Alternately:
@@ -454,14 +479,12 @@ def _transform_pandas_df(
454
479
meta : Optional [str ] = None ,
455
480
meta_type : Optional [NumpyDType ] = None ,
456
481
) -> Tuple [np .ndarray , Optional [FeatureNames ], Optional [FeatureTypes ]]:
457
- from pandas .api .types import is_categorical_dtype , is_sparse
458
-
459
482
pyarrow_extension = False
460
483
for dtype in data .dtypes :
461
484
if not (
462
485
(dtype .name in _pandas_dtype_mapper )
463
- or is_sparse (dtype )
464
- or (is_categorical_dtype (dtype ) and enable_categorical )
486
+ or is_pd_sparse_dtype (dtype )
487
+ or (is_pd_cat_dtype (dtype ) and enable_categorical )
465
488
or is_pa_ext_dtype (dtype )
466
489
):
467
490
_invalid_dataframe_dtype (data )
@@ -515,9 +538,8 @@ def _meta_from_pandas_series(
515
538
) -> None :
516
539
"""Help transform pandas series for meta data like labels"""
517
540
data = data .values .astype ("float" )
518
- from pandas .api .types import is_sparse
519
541
520
- if is_sparse ( data ):
542
+ if is_pd_sparse_dtype ( getattr ( data , "dtype" , data ) ):
521
543
data = data .to_dense () # type: ignore
522
544
assert len (data .shape ) == 1 or data .shape [1 ] == 0 or data .shape [1 ] == 1
523
545
_meta_from_numpy (data , name , dtype , handle )
@@ -539,13 +561,11 @@ def _from_pandas_series(
539
561
feature_names : Optional [FeatureNames ],
540
562
feature_types : Optional [FeatureTypes ],
541
563
) -> DispatchedDataBackendReturnType :
542
- from pandas .api .types import is_categorical_dtype
543
-
544
564
if (data .dtype .name not in _pandas_dtype_mapper ) and not (
545
- is_categorical_dtype (data .dtype ) and enable_categorical
565
+ is_pd_cat_dtype (data .dtype ) and enable_categorical
546
566
):
547
567
_invalid_dataframe_dtype (data )
548
- if enable_categorical and is_categorical_dtype (data .dtype ):
568
+ if enable_categorical and is_pd_cat_dtype (data .dtype ):
549
569
data = data .cat .codes
550
570
return _from_numpy_array (
551
571
data .values .reshape (data .shape [0 ], 1 ).astype ("float" ),
0 commit comments