Skip to content

BUG: fix bool no-op replace calls #6339

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Feb 13, 2014
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions doc/source/release.rst
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,8 @@ Bug Fixes
- ``HDFStore.select_as_coordinates`` and ``select_column`` works where clauses that result in filters (:issue:`6177`)
- Regression in join of non_unique_indexes (:issue:`6329`)
- Issue with groupby ``agg`` with a single function and a a mixed-type frame (:issue:`6337`)
- Bug in ``DataFrame.replace()`` when passing a non- ``bool``
``to_replace`` argument (:issue:`6332`)

pandas 0.13.1
-------------
Expand Down
9 changes: 9 additions & 0 deletions pandas/core/internals.py
Original file line number Diff line number Diff line change
Expand Up @@ -1216,6 +1216,7 @@ def should_store(self, value):
return (issubclass(value.dtype.type, np.floating) and
value.dtype == self.dtype)


class ComplexBlock(FloatOrComplexBlock):
is_complex = True

Expand Down Expand Up @@ -1355,6 +1356,14 @@ def _try_cast(self, element):
def should_store(self, value):
return issubclass(value.dtype.type, np.bool_)

def replace(self, to_replace, value, inplace=False, filter=None,
regex=False):
to_replace_values = np.atleast_1d(to_replace)
if not np.can_cast(to_replace_values, bool):
to_replace = to_replace_values
return super(BoolBlock, self).replace(to_replace, value,
inplace=inplace, filter=filter,
regex=regex)

class ObjectBlock(Block):
is_object = True
Expand Down
25 changes: 24 additions & 1 deletion pandas/tests/test_frame.py
Original file line number Diff line number Diff line change
Expand Up @@ -7975,7 +7975,7 @@ def test_replace_dict_tuple_list_ordering_remains_the_same(self):
tm.assert_frame_equal(res2, res3)
tm.assert_frame_equal(res3, expected)

def test_replace_doesnt_replace_with_no_regex(self):
def test_replace_doesnt_replace_without_regex(self):
from pandas.compat import StringIO
raw = """fol T_opp T_Dir T_Enh
0 1 0 0 vo
Expand All @@ -7986,6 +7986,29 @@ def test_replace_doesnt_replace_with_no_regex(self):
res = df.replace({'\D': 1})
tm.assert_frame_equal(df, res)

def test_replace_bool_with_string(self):
df = DataFrame({'a': [True, False], 'b': list('ab')})
result = df.replace(True, 'a')
expected = DataFrame({'a': ['a', False], 'b': df.b})
tm.assert_frame_equal(result, expected)

def test_replace_pure_bool_with_string_no_op(self):
df = DataFrame(np.random.rand(2, 2) > 0.5)
result = df.replace('asdf', 'fdsa')
tm.assert_frame_equal(df, result)

def test_replace_bool_with_bool(self):
df = DataFrame(np.random.rand(2, 2) > 0.5)
result = df.replace(False, True)
expected = DataFrame(np.ones((2, 2), dtype=bool))
tm.assert_frame_equal(result, expected)

def test_replace_with_dict_with_bool_keys(self):
df = DataFrame({0: [True, False], 1: [False, True]})
result = df.replace({'asdf': 'asdb', True: 'yes'})
expected = DataFrame({0: ['yes', False], 1: [False, 'yes']})
tm.assert_frame_equal(expected, result)

def test_combine_multiple_frames_dtypes(self):
from pandas import concat

Expand Down
26 changes: 25 additions & 1 deletion pandas/tests/test_series.py
Original file line number Diff line number Diff line change
Expand Up @@ -5291,7 +5291,6 @@ def test_replace(self):
result = ser.replace(Timestamp('20130103'), Timestamp('20120101'))
assert_series_equal(result, expected)


def test_replace_with_single_list(self):
ser = Series([0, 1, 2, 3, 4])
result = ser.replace([1,2,3])
Expand All @@ -5307,6 +5306,7 @@ def test_replace_with_single_list(self):
s.replace([1,2,3],inplace=True,method='crash_cymbal')
assert_series_equal(s, ser)


def test_replace_mixed_types(self):
s = Series(np.arange(5),dtype='int64')

Expand Down Expand Up @@ -5349,6 +5349,30 @@ def check_replace(to_rep, val, expected):
assert_series_equal(r, Series([1.0,2,'a'] +
dr[3:].tolist(),dtype=object))

def test_replace_bool_with_string_no_op(self):
s = Series([True, False, True])
result = s.replace('fun', 'in-the-sun')
tm.assert_series_equal(s, result)

def test_replace_bool_with_string(self):
# nonexistent elements
s = Series([True, False, True])
result = s.replace(True, '2u')
expected = Series(['2u', False, '2u'])
tm.assert_series_equal(expected, result)

def test_replace_bool_with_bool(self):
s = Series([True, False, True])
result = s.replace(True, False)
expected = Series([False] * len(s))
tm.assert_series_equal(expected, result)

def test_replace_with_dict_with_bool_keys(self):
s = Series([True, False, True])
result = s.replace({'asdf': 'asdb', True: 'yes'})
expected = Series(['yes', False, 'yes'])
tm.assert_series_equal(expected, result)

def test_asfreq(self):
ts = Series([0., 1., 2.], index=[datetime(2009, 10, 30),
datetime(2009, 11, 30),
Expand Down