@@ -342,6 +342,57 @@ def _from_scalars(cls, scalars, dtype: DtypeObj) -> Self:
342
342
raise ValueError
343
343
return cls ._from_sequence (scalars , dtype = dtype )
344
344
345
+ def _str_map (
346
+ self , f , na_value = None , dtype : Dtype | None = None , convert : bool = True
347
+ ):
348
+ if self .dtype .na_value is np .nan :
349
+ return self ._str_map_nan_semantics (
350
+ f , na_value = na_value , dtype = dtype , convert = convert
351
+ )
352
+
353
+ from pandas .arrays import BooleanArray
354
+
355
+ if dtype is None :
356
+ dtype = self .dtype
357
+ if na_value is None :
358
+ na_value = self .dtype .na_value
359
+
360
+ mask = isna (self )
361
+ arr = np .asarray (self )
362
+
363
+ if is_integer_dtype (dtype ) or is_bool_dtype (dtype ):
364
+ constructor : type [IntegerArray | BooleanArray ]
365
+ if is_integer_dtype (dtype ):
366
+ constructor = IntegerArray
367
+ else :
368
+ constructor = BooleanArray
369
+
370
+ na_value_is_na = isna (na_value )
371
+ if na_value_is_na :
372
+ na_value = 1
373
+ elif dtype == np .dtype ("bool" ):
374
+ # GH#55736
375
+ na_value = bool (na_value )
376
+ result = lib .map_infer_mask (
377
+ arr ,
378
+ f ,
379
+ mask .view ("uint8" ),
380
+ convert = False ,
381
+ na_value = na_value ,
382
+ # error: Argument 1 to "dtype" has incompatible type
383
+ # "Union[ExtensionDtype, str, dtype[Any], Type[object]]"; expected
384
+ # "Type[object]"
385
+ dtype = np .dtype (cast (type , dtype )),
386
+ )
387
+
388
+ if not na_value_is_na :
389
+ mask [:] = False
390
+
391
+ return constructor (result , mask )
392
+
393
+ else :
394
+ return self ._str_map_str_or_object (dtype , na_value , arr , f , mask , convert )
395
+
345
396
def _str_map_str_or_object (
346
397
self ,
347
398
dtype ,
@@ -373,6 +424,45 @@ def _str_map_str_or_object(
373
424
# -> We don't know the result type. E.g. `.get` can return anything.
374
425
return lib .map_infer_mask (arr , f , mask .view ("uint8" ))
375
426
427
+ def _str_map_nan_semantics (
428
+ self , f , na_value = None , dtype : Dtype | None = None , convert : bool = True
429
+ ):
430
+ if dtype is None :
431
+ dtype = self .dtype
432
+ if na_value is None :
433
+ na_value = self .dtype .na_value
434
+
435
+ mask = isna (self )
436
+ arr = np .asarray (self )
437
+ convert = convert and not np .all (mask )
438
+
439
+ if is_integer_dtype (dtype ) or is_bool_dtype (dtype ):
440
+ na_value_is_na = isna (na_value )
441
+ if na_value_is_na :
442
+ if is_integer_dtype (dtype ):
443
+ na_value = 0
444
+ else :
445
+ na_value = True
446
+
447
+ result = lib .map_infer_mask (
448
+ arr ,
449
+ f ,
450
+ mask .view ("uint8" ),
451
+ convert = False ,
452
+ na_value = na_value ,
453
+ dtype = np .dtype (cast (type , dtype )),
454
+ )
455
+ if na_value_is_na and mask .any ():
456
+ if is_integer_dtype (dtype ):
457
+ result = result .astype ("float64" )
458
+ else :
459
+ result = result .astype ("object" )
460
+ result [mask ] = np .nan
461
+ return result
462
+
463
+ else :
464
+ return self ._str_map_str_or_object (dtype , na_value , arr , f , mask , convert )
465
+
376
466
377
467
# error: Definition of "_concat_same_type" in base class "NDArrayBacked" is
378
468
# incompatible with definition in base class "ExtensionArray"
@@ -727,95 +817,6 @@ def _cmp_method(self, other, op):
727
817
# base class "NumpyExtensionArray" defined the type as "float")
728
818
_str_na_value = libmissing .NA # type: ignore[assignment]
729
819
730
- def _str_map_nan_semantics (
731
- self , f , na_value = None , dtype : Dtype | None = None , convert : bool = True
732
- ):
733
- if dtype is None :
734
- dtype = self .dtype
735
- if na_value is None :
736
- na_value = self .dtype .na_value
737
-
738
- mask = isna (self )
739
- arr = np .asarray (self )
740
- convert = convert and not np .all (mask )
741
-
742
- if is_integer_dtype (dtype ) or is_bool_dtype (dtype ):
743
- na_value_is_na = isna (na_value )
744
- if na_value_is_na :
745
- if is_integer_dtype (dtype ):
746
- na_value = 0
747
- else :
748
- na_value = True
749
-
750
- result = lib .map_infer_mask (
751
- arr ,
752
- f ,
753
- mask .view ("uint8" ),
754
- convert = False ,
755
- na_value = na_value ,
756
- dtype = np .dtype (cast (type , dtype )),
757
- )
758
- if na_value_is_na and mask .any ():
759
- if is_integer_dtype (dtype ):
760
- result = result .astype ("float64" )
761
- else :
762
- result = result .astype ("object" )
763
- result [mask ] = np .nan
764
- return result
765
-
766
- else :
767
- return self ._str_map_str_or_object (dtype , na_value , arr , f , mask , convert )
768
-
769
- def _str_map (
770
- self , f , na_value = None , dtype : Dtype | None = None , convert : bool = True
771
- ):
772
- if self .dtype .na_value is np .nan :
773
- return self ._str_map_nan_semantics (
774
- f , na_value = na_value , dtype = dtype , convert = convert
775
- )
776
-
777
- from pandas .arrays import BooleanArray
778
-
779
- if dtype is None :
780
- dtype = StringDtype (storage = "python" )
781
- if na_value is None :
782
- na_value = self .dtype .na_value
783
-
784
- mask = isna (self )
785
- arr = np .asarray (self )
786
-
787
- if is_integer_dtype (dtype ) or is_bool_dtype (dtype ):
788
- constructor : type [IntegerArray | BooleanArray ]
789
- if is_integer_dtype (dtype ):
790
- constructor = IntegerArray
791
- else :
792
- constructor = BooleanArray
793
-
794
- na_value_is_na = isna (na_value )
795
- if na_value_is_na :
796
- na_value = 1
797
- elif dtype == np .dtype ("bool" ):
798
- na_value = bool (na_value )
799
- result = lib .map_infer_mask (
800
- arr ,
801
- f ,
802
- mask .view ("uint8" ),
803
- convert = False ,
804
- na_value = na_value ,
805
- # error: Argument 1 to "dtype" has incompatible type
806
- # "Union[ExtensionDtype, str, dtype[Any], Type[object]]"; expected
807
- # "Type[object]"
808
- dtype = np .dtype (dtype ), # type: ignore[arg-type]
809
- )
810
-
811
- if not na_value_is_na :
812
- mask [:] = False
813
-
814
- return constructor (result , mask )
815
-
816
- else :
817
- return self ._str_map_str_or_object (dtype , na_value , arr , f , mask , convert )
818
-
819
820
820
821
class StringArrayNumpySemantics (StringArray ):
821
822
_storage = "python"
0 commit comments