Skip to content

Commit 161376f

Browse files
committed
Merge pull request #7657 from jreback/where
API: disallow inplace setting with where and a non-np.nan value (GH7656)
2 parents 8cd3dd6 + 06e2808 commit 161376f

File tree

4 files changed

+31
-12
lines changed

4 files changed

+31
-12
lines changed

doc/source/v0.14.1.txt

+2-5
Original file line numberDiff line numberDiff line change
@@ -24,11 +24,6 @@ users upgrade to this version.
2424
API changes
2525
~~~~~~~~~~~
2626

27-
28-
29-
30-
31-
3227
- All ``offsets`` suppports ``normalize`` keyword to specify whether ``offsets.apply``, ``rollforward`` and ``rollback`` resets time (hour, minute, etc) or not (default ``False``, preserves time) (:issue:`7156`)
3328

3429

@@ -60,6 +55,8 @@ API changes
6055

6156
- Bug in ``.loc`` performing fallback integer indexing with ``object`` dtype indices (:issue:`7496`)
6257
- Add back ``#N/A N/A`` as a default NA value in text parsing, (regresion from 0.12) (:issue:`5521`)
58+
- Raise a ``TypeError`` on inplace-setting with a ``.where`` and a non ``np.nan`` value as this is inconsistent
59+
with a set-item expression like ``df[mask] = None`` (:issue:`7656`)
6360

6461
.. _whatsnew_0141.prior_deprecations:
6562

pandas/core/frame.py

+3-7
Original file line numberDiff line numberDiff line change
@@ -679,8 +679,8 @@ def to_gbq(self, destination_table, project_id=None, chunksize=10000,
679679
the defined table schema and column types. For simplicity, this method
680680
uses the Google BigQuery streaming API. The to_gbq method chunks data
681681
into a default chunk size of 10,000. Failures return the complete error
682-
response which can be quite long depending on the size of the insert.
683-
There are several important limitations of the Google streaming API
682+
response which can be quite long depending on the size of the insert.
683+
There are several important limitations of the Google streaming API
684684
which are detailed at:
685685
https://developers.google.com/bigquery/streaming-data-into-bigquery.
686686
@@ -1925,11 +1925,7 @@ def _setitem_frame(self, key, value):
19251925
if key.values.dtype != np.bool_:
19261926
raise TypeError('Must pass DataFrame with boolean values only')
19271927

1928-
if self._is_mixed_type:
1929-
if not self._is_numeric_mixed_type:
1930-
raise TypeError(
1931-
'Cannot do boolean setting on mixed-type frame')
1932-
1928+
self._check_inplace_setting(value)
19331929
self._check_setitem_copy()
19341930
self.where(-key, value, inplace=True)
19351931

pandas/core/generic.py

+20
Original file line numberDiff line numberDiff line change
@@ -1910,6 +1910,24 @@ def _is_datelike_mixed_type(self):
19101910
f = lambda: self._data.is_datelike_mixed_type
19111911
return self._protect_consolidate(f)
19121912

1913+
def _check_inplace_setting(self, value):
1914+
""" check whether we allow in-place setting with this type of value """
1915+
1916+
if self._is_mixed_type:
1917+
if not self._is_numeric_mixed_type:
1918+
1919+
# allow an actual np.nan thru
1920+
try:
1921+
if np.isnan(value):
1922+
return True
1923+
except:
1924+
pass
1925+
1926+
raise TypeError(
1927+
'Cannot do inplace boolean setting on mixed-types with a non np.nan value')
1928+
1929+
return True
1930+
19131931
def _protect_consolidate(self, f):
19141932
blocks_before = len(self._data.blocks)
19151933
result = f()
@@ -3214,6 +3232,8 @@ def where(self, cond, other=np.nan, inplace=False, axis=None, level=None,
32143232
if inplace:
32153233
# we may have different type blocks come out of putmask, so
32163234
# reconstruct the block manager
3235+
3236+
self._check_inplace_setting(other)
32173237
new_data = self._data.putmask(mask=cond, new=other, align=axis is None,
32183238
inplace=True)
32193239
self._update_inplace(new_data)

pandas/tests/test_frame.py

+6
Original file line numberDiff line numberDiff line change
@@ -9242,6 +9242,12 @@ def test_where_none(self):
92429242
expected = DataFrame({'series': Series([0,1,2,3,4,5,6,7,np.nan,np.nan]) })
92439243
assert_frame_equal(df, expected)
92449244

9245+
# GH 7656
9246+
df = DataFrame([{'A': 1, 'B': np.nan, 'C': 'Test'}, {'A': np.nan, 'B': 'Test', 'C': np.nan}])
9247+
expected = df.where(~isnull(df), None)
9248+
with tm.assertRaisesRegexp(TypeError, 'boolean setting on mixed-type'):
9249+
df.where(~isnull(df), None, inplace=True)
9250+
92459251
def test_where_align(self):
92469252

92479253
def create():

0 commit comments

Comments
 (0)