17
17
)
18
18
from pandas ._libs .internals import BlockPlacement
19
19
from pandas ._libs .tslibs import conversion
20
- from pandas ._typing import ArrayLike , Dtype , DtypeObj , Scalar , Shape
20
+ from pandas ._typing import ArrayLike , Dtype , DtypeObj , Shape
21
21
from pandas .util ._validators import validate_bool_kwarg
22
22
23
23
from pandas .core .dtypes .cast import (
44
44
is_integer ,
45
45
is_list_like ,
46
46
is_object_dtype ,
47
- is_re ,
48
- is_re_compilable ,
49
47
is_sparse ,
50
48
pandas_dtype ,
51
49
)
59
57
putmask_smart ,
60
58
putmask_without_repeat ,
61
59
)
62
- from pandas .core .array_algos .replace import compare_or_regex_search , replace_regex
60
+ from pandas .core .array_algos .replace import (
61
+ compare_or_regex_search ,
62
+ replace_regex ,
63
+ should_use_regex ,
64
+ )
63
65
from pandas .core .array_algos .transforms import shift
64
66
from pandas .core .arrays import (
65
67
Categorical ,
@@ -817,6 +819,12 @@ def _replace_list(
817
819
"""
818
820
See BlockManager._replace_list docstring.
819
821
"""
822
+ # TODO: dont special-case Categorical
823
+ if self .is_categorical and len (algos .unique (dest_list )) == 1 :
824
+ # We likely got here by tiling value inside NDFrame.replace,
825
+ # so un-tile here
826
+ return self .replace (src_list , dest_list [0 ], inplace , regex )
827
+
820
828
# Exclude anything that we know we won't contain
821
829
pairs = [
822
830
(x , y ) for x , y in zip (src_list , dest_list ) if self ._can_hold_element (x )
@@ -827,21 +835,14 @@ def _replace_list(
827
835
828
836
src_len = len (pairs ) - 1
829
837
830
- def comp (s : Scalar , mask : np .ndarray , regex : bool = False ) -> np .ndarray :
831
- """
832
- Generate a bool array by perform an equality check, or perform
833
- an element-wise regular expression matching
834
- """
835
- if isna (s ):
836
- return ~ mask
837
-
838
- return compare_or_regex_search (self .values , s , regex , mask )
839
-
840
838
if self .is_object :
841
839
# Calculate the mask once, prior to the call of comp
842
840
# in order to avoid repeating the same computations
843
841
mask = ~ isna (self .values )
844
- masks = [comp (s [0 ], mask , regex ) for s in pairs ]
842
+ masks = [
843
+ compare_or_regex_search (self .values , s [0 ], regex = regex , mask = mask )
844
+ for s in pairs
845
+ ]
845
846
else :
846
847
# GH#38086 faster if we know we dont need to check for regex
847
848
masks = [missing .mask_missing (self .values , s [0 ]) for s in pairs ]
@@ -1464,7 +1465,7 @@ def _replace_coerce(
1464
1465
putmask_inplace (nb .values , mask , value )
1465
1466
return [nb ]
1466
1467
else :
1467
- regex = _should_use_regex (regex , to_replace )
1468
+ regex = should_use_regex (regex , to_replace )
1468
1469
if regex :
1469
1470
return self ._replace_regex (
1470
1471
to_replace ,
@@ -2353,44 +2354,17 @@ def replace(
2353
2354
# here with listlike to_replace or value, as those cases
2354
2355
# go through _replace_list
2355
2356
2356
- regex = _should_use_regex (regex , to_replace )
2357
+ regex = should_use_regex (regex , to_replace )
2357
2358
2358
2359
if regex :
2359
2360
return self ._replace_regex (to_replace , value , inplace = inplace )
2360
2361
else :
2361
2362
return super ().replace (to_replace , value , inplace = inplace , regex = False )
2362
2363
2363
2364
2364
- def _should_use_regex (regex : bool , to_replace : Any ) -> bool :
2365
- """
2366
- Decide whether to treat `to_replace` as a regular expression.
2367
- """
2368
- if is_re (to_replace ):
2369
- regex = True
2370
-
2371
- regex = regex and is_re_compilable (to_replace )
2372
-
2373
- # Don't use regex if the pattern is empty.
2374
- regex = regex and re .compile (to_replace ).pattern != ""
2375
- return regex
2376
-
2377
-
2378
2365
class CategoricalBlock (ExtensionBlock ):
2379
2366
__slots__ = ()
2380
2367
2381
- def _replace_list (
2382
- self ,
2383
- src_list : List [Any ],
2384
- dest_list : List [Any ],
2385
- inplace : bool = False ,
2386
- regex : bool = False ,
2387
- ) -> List [Block ]:
2388
- if len (algos .unique (dest_list )) == 1 :
2389
- # We likely got here by tiling value inside NDFrame.replace,
2390
- # so un-tile here
2391
- return self .replace (src_list , dest_list [0 ], inplace , regex )
2392
- return super ()._replace_list (src_list , dest_list , inplace , regex )
2393
-
2394
2368
def replace (
2395
2369
self ,
2396
2370
to_replace ,
0 commit comments