Skip to content

Commit e2a07cb

Browse files
committed
BUG: in-place conversion of integer series to float (on putmasking), GH #2746
1 parent 13ae597 commit e2a07cb

File tree

5 files changed

+38
-3
lines changed

5 files changed

+38
-3
lines changed

RELEASE.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,9 +120,12 @@ pandas 0.11.0
120120
- Support null checking on timedelta64, representing (and formatting) with NaT
121121
- Support setitem with np.nan value, converts to NaT
122122

123+
- Bug on in-place putmasking on an ``integer`` series that needs to be converted to ``float`` (GH2746_)
124+
123125
.. _GH622: https://github.com/pydata/pandas/issues/622
124126
.. _GH797: https://github.com/pydata/pandas/issues/797
125127
.. _GH2681: https://github.com/pydata/pandas/issues/2681
128+
.. _GH2746: https://github.com/pydata/pandas/issues/2746
126129
.. _GH2747: https://github.com/pydata/pandas/issues/2747
127130
.. _GH2751: https://github.com/pydata/pandas/issues/2751
128131
.. _GH2776: https://github.com/pydata/pandas/issues/2776

pandas/core/common.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -722,6 +722,20 @@ def _maybe_promote(dtype, fill_value=np.nan):
722722
return dtype, fill_value
723723

724724

725+
def _maybe_upcast_putmask(result, mask, other):
726+
""" a safe version of put mask that (potentially upcasts the result
727+
return the result and a changed flag """
728+
try:
729+
np.putmask(result, mask, other)
730+
except:
731+
# our type is wrong here, need to upcast
732+
if (-mask).any():
733+
result, fill_value = _maybe_upcast(result, copy=True)
734+
np.putmask(result, mask, other)
735+
return result, True
736+
737+
return result, False
738+
725739
def _maybe_upcast(values, fill_value=np.nan, copy=False):
726740
""" provide explicty type promotion and coercion
727741
if copy == True, then a copy is created even if no upcast is required """

pandas/core/frame.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -201,7 +201,7 @@ def na_op(x, y):
201201
mask = notnull(xrav)
202202
result[mask] = op(xrav[mask], y)
203203

204-
np.putmask(result, -mask, NA)
204+
result, changed = com._maybe_upcast_putmask(result,-mask,np.nan)
205205
result = result.reshape(x.shape)
206206

207207
return result

pandas/core/series.py

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,8 @@ def na_op(x, y):
7070
else:
7171
mask = notnull(x)
7272
result[mask] = op(x[mask], y)
73-
np.putmask(result, -mask, pa.NA)
73+
74+
result, changed = com._maybe_upcast_putmask(result,-mask,pa.NA)
7475

7576
return result
7677

@@ -680,7 +681,13 @@ def where(self, cond, other=nan, inplace=False):
680681
if len(other) != len(ser):
681682
raise ValueError('Length of replacements must equal series length')
682683

683-
np.putmask(ser, ~cond, other)
684+
result, changed = com._maybe_upcast_putmask(ser,~cond,other)
685+
if changed:
686+
687+
# need to actually change ser here
688+
if inplace:
689+
ser.dtype = result.dtype
690+
ser[:] = result
684691

685692
return None if inplace else ser
686693

pandas/tests/test_series.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2943,6 +2943,17 @@ def test_asof_more(self):
29432943
result = s.asof(s.index[0])
29442944
self.assertEqual(result, s[0])
29452945

2946+
def test_cast_on_putmask(self):
2947+
2948+
# GH 2746
2949+
2950+
# need to upcast
2951+
s = Series([1,2],index=[1,2],dtype='int64')
2952+
s[[True, False]] = Series([0],index=[1],dtype='int64')
2953+
expected = Series([0,2],index=[1,2],dtype='float64')
2954+
2955+
assert_series_equal(s, expected)
2956+
29462957
def test_astype_cast_nan_int(self):
29472958
df = Series([1.0, 2.0, 3.0, np.nan])
29482959
self.assertRaises(ValueError, df.astype, np.int64)

0 commit comments

Comments
 (0)