Merged
Show file tree
Hide file tree
Changes from all commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Failed to load files.
Original file line numberDiff line numberDiff line change
Expand Up@@ -370,6 +370,7 @@ Interval
Indexing
^^^^^^^^
- Bug in :meth:`DataFrame.__setitem__` losing dtype when setting a :class:`DataFrame` into duplicated columns (:issue:`53143`)
- Bug in :meth:`DataFrame.__setitem__` with a boolean mask and :meth:`DataFrame.putmask` with mixed non-numeric dtypes and a value other than ``NaN`` incorrectly raising ``TypeError`` (:issue:`53291`)
-

Missing
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -4074,7 +4074,6 @@ def _setitem_frame(self, key, value):
"Must pass DataFrame or 2-d ndarray with boolean values only"
)

self._check_inplace_setting(value)
self._check_setitem_copy()
self._where(-key, value, inplace=True)

Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -114,7 +114,6 @@
is_bool_dtype,
is_dict_like,
is_extension_array_dtype,
is_float,
is_list_like,
is_number,
is_numeric_dtype,
Expand DownExpand Up@@ -6201,21 +6200,6 @@ def _is_mixed_type(self) -> bool_t:

return self.dtypes.nunique() > 1

@final
def _check_inplace_setting(self, value) -> bool_t:
"""check whether we allow in-place setting with this type of value"""
if self._is_mixed_type and not self._mgr.is_numeric_mixed_type:
# allow an actual np.nan through
if (is_float(value) and np.isnan(value)) or value is lib.no_default:
return True

raise TypeError(
"Cannot do inplace boolean setting on "
"mixed-types with a non np.nan value"
)

return True

@final
def _get_numeric_data(self) -> Self:
return self._constructor(self._mgr.get_numeric_data()).__finalize__(self)
Expand DownExpand Up@@ -10036,7 +10020,6 @@ def _where(
# we may have different type blocks come out of putmask, so
# reconstruct the block manager

self._check_inplace_setting(other)
new_data = self._mgr.putmask(mask=cond, new=other, align=align)
result = self._constructor(new_data)
return self._update_inplace(result)
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -514,10 +514,6 @@ def to_native_types(self, **kwargs) -> Self:
"""
return self.apply("to_native_types", **kwargs)

@property
def is_numeric_mixed_type(self) -> bool:
return all(block.is_numeric for block in self.blocks)

@property
def any_extension_types(self) -> bool:
"""Whether any of the blocks in this manager are extension blocks"""
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -401,10 +401,23 @@ def test_where_none(self):
{"A": np.nan, "B": "Test", "C": np.nan},
]
)
msg = "boolean setting on mixed-type"

with pytest.raises(TypeError, match=msg):
df.where(~isna(df), None, inplace=True)
orig = df.copy()

mask = ~isna(df)
df.where(mask, None, inplace=True)
expected = DataFrame(
{
"A": [1.0, np.nan],
"B": [None, "Test"],
"C": ["Test", None],
}
)
tm.assert_frame_equal(df, expected)

df = orig.copy()
df[~mask] = None
tm.assert_frame_equal(df, expected)

def test_where_empty_df_and_empty_cond_having_non_bool_dtypes(self):
# see gh-21947
Expand Down