@@ -738,8 +738,11 @@ def replace(
738
738
# If we cannot replace with own dtype, convert to ObjectBlock and
739
739
# retry
740
740
if not self ._can_hold_element (to_replace ):
741
- # TODO: we should be able to infer at this point that there is
742
- # nothing to replace
741
+ if not isinstance (to_replace , list ):
742
+ if inplace :
743
+ return [self ]
744
+ return [self .copy ()]
745
+
743
746
# GH 22083, TypeError or ValueError occurred within error handling
744
747
# causes infinite loop. Cast and retry only if not objectblock.
745
748
if is_object_dtype (self ):
@@ -764,14 +767,27 @@ def replace(
764
767
filtered_out = ~ self .mgr_locs .isin (filter )
765
768
mask [filtered_out .nonzero ()[0 ]] = False
766
769
770
+ if not mask .any ():
771
+ if inplace :
772
+ return [self ]
773
+ return [self .copy ()]
774
+
767
775
try :
768
776
blocks = self .putmask (mask , value , inplace = inplace )
777
+ # Note: it is _not_ the case that self._can_hold_element(value)
778
+ # is always true at this point. In particular, that can fail
779
+ # for:
780
+ # "2u" with bool-dtype, float-dtype
781
+ # 0.5 with int64-dtype
782
+ # np.nan with int64-dtype
769
783
except (TypeError , ValueError ):
770
784
# GH 22083, TypeError or ValueError occurred within error handling
771
785
# causes infinite loop. Cast and retry only if not objectblock.
772
786
if is_object_dtype (self ):
773
787
raise
774
788
789
+ assert not self ._can_hold_element (value ), value
790
+
775
791
# try again with a compatible block
776
792
block = self .astype (object )
777
793
return block .replace (
@@ -924,6 +940,7 @@ def putmask(self, mask, new, align=True, inplace=False, axis=0, transpose=False)
924
940
925
941
# if we are passed a scalar None, convert it here
926
942
if not is_list_like (new ) and isna (new ) and not self .is_object :
943
+ # FIXME: make sure we have compatible NA
927
944
new = self .fill_value
928
945
929
946
if self ._can_hold_element (new ):
0 commit comments