Skip to content

Commit 7f02585

Browse files
committed
Merge pull request #3050 from jreback/numerics_3037
ENH: Allow setitem in a frame where only mixed numerics are present
2 parents e9b2c02 + e70aec5 commit 7f02585

File tree

6 files changed

+51
-7
lines changed

6 files changed

+51
-7
lines changed

RELEASE.rst

+2
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ pandas 0.11.0
6262
strings that can be parsed with datetime.strptime
6363
- Add ``axes`` property to ``Series`` for compatibility
6464
- Add ``xs`` function to ``Series`` for compatibility
65+
- Allow setitem in a frame where only mixed numerics are present (e.g. int and float), (GH3037_)
6566

6667
**API Changes**
6768

@@ -182,6 +183,7 @@ pandas 0.11.0
182183
.. _GH3010: https://github.com/pydata/pandas/issues/3010
183184
.. _GH3012: https://github.com/pydata/pandas/issues/3012
184185
.. _GH3029: https://github.com/pydata/pandas/issues/3029
186+
.. _GH3037: https://github.com/pydata/pandas/issues/3037
185187
.. _GH3041: https://github.com/pydata/pandas/issues/3041
186188
.. _GH3053: https://github.com/pydata/pandas/issues/3053
187189

pandas/core/frame.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -2121,7 +2121,8 @@ def _setitem_frame(self, key, value):
21212121
raise ValueError('Must pass DataFrame with boolean values only')
21222122

21232123
if self._is_mixed_type:
2124-
raise ValueError('Cannot do boolean setting on mixed-type frame')
2124+
if not self._is_numeric_mixed_type:
2125+
raise ValueError('Cannot do boolean setting on mixed-type frame')
21252126

21262127
self.where(-key, value, inplace=True)
21272128

pandas/core/generic.py

+5-2
Original file line numberDiff line numberDiff line change
@@ -671,8 +671,11 @@ def consolidate(self, inplace=False):
671671

672672
@property
673673
def _is_mixed_type(self):
674-
self._consolidate_inplace()
675-
return len(self._data.blocks) > 1
674+
return self._data.is_mixed_type
675+
676+
@property
677+
def _is_numeric_mixed_type(self):
678+
return self._data.is_numeric_mixed_type
676679

677680
def _reindex_axis(self, new_index, fill_method, axis, copy):
678681
new_data = self._data.reindex_axis(new_index, axis=axis,

pandas/core/internals.py

+14-3
Original file line numberDiff line numberDiff line change
@@ -980,6 +980,16 @@ def _consolidate_check(self):
980980
self._is_consolidated = len(dtypes) == len(set(dtypes))
981981
self._known_consolidated = True
982982

983+
@property
984+
def is_mixed_type(self):
985+
self._consolidate_inplace()
986+
return len(self.blocks) > 1
987+
988+
@property
989+
def is_numeric_mixed_type(self):
990+
self._consolidate_inplace()
991+
return all([ block.is_numeric for block in self.blocks ])
992+
983993
def get_numeric_data(self, copy=False, type_list=None, as_blocks = False):
984994
"""
985995
Parameters
@@ -1227,9 +1237,10 @@ def consolidate(self):
12271237
return BlockManager(new_blocks, self.axes)
12281238

12291239
def _consolidate_inplace(self):
1230-
self.blocks = _consolidate(self.blocks, self.items)
1231-
self._is_consolidated = True
1232-
self._known_consolidated = True
1240+
if not self.is_consolidated():
1241+
self.blocks = _consolidate(self.blocks, self.items)
1242+
self._is_consolidated = True
1243+
self._known_consolidated = True
12331244

12341245
def get(self, item):
12351246
_, block = self._find_block(item)

pandas/core/reshape.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,7 @@ def get_new_values(self):
159159
dtype, fill_value = _maybe_promote(values.dtype)
160160
new_values = np.empty(result_shape, dtype=dtype)
161161
new_values.fill(fill_value)
162-
162+
163163
new_mask = np.zeros(result_shape, dtype=bool)
164164

165165
# is there a simpler / faster way of doing this?

pandas/tests/test_frame.py

+27
Original file line numberDiff line numberDiff line change
@@ -8660,6 +8660,33 @@ def test_boolean_indexing(self):
86608660
df1[df1 > 2.0 * df2] = -1
86618661
assert_frame_equal(df1, expected)
86628662

8663+
def test_boolean_indexing_mixed(self):
8664+
df = DataFrame(
8665+
{0L: {35: np.nan, 40: np.nan, 43: np.nan, 49: np.nan, 50: np.nan},
8666+
1L: {35: np.nan,
8667+
40: 0.32632316859446198,
8668+
43: np.nan,
8669+
49: 0.32632316859446198,
8670+
50: 0.39114724480578139},
8671+
2L: {35: np.nan, 40: np.nan, 43: 0.29012581014105987, 49: np.nan, 50: np.nan},
8672+
3L: {35: np.nan, 40: np.nan, 43: np.nan, 49: np.nan, 50: np.nan},
8673+
4L: {35: 0.34215328467153283, 40: np.nan, 43: np.nan, 49: np.nan, 50: np.nan},
8674+
'y': {35: 0, 40: 0, 43: 0, 49: 0, 50: 1}})
8675+
8676+
# mixed int/float ok
8677+
df2 = df.copy()
8678+
df2[df2>0.3] = 1
8679+
expected = df.copy()
8680+
expected.loc[40,1] = 1
8681+
expected.loc[49,1] = 1
8682+
expected.loc[50,1] = 1
8683+
expected.loc[35,4] = 1
8684+
assert_frame_equal(df2,expected)
8685+
8686+
# add object, should this raise?
8687+
df['foo'] = 'test'
8688+
self.assertRaises(ValueError, df.__setitem__, df>0.3, 1)
8689+
86638690
def test_sum_bools(self):
86648691
df = DataFrame(index=range(1), columns=range(10))
86658692
bools = isnull(df)

0 commit comments

Comments
 (0)