Skip to content

BUG: (GH4192) Fixed buglet in the broadcasting logic in Series.where #4195

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 2 commits into from
Jul 10, 2013
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
3 changes: 3 additions & 0 deletions doc/source/release.rst
Original file line number Diff line number Diff line change
Expand Up @@ -324,6 +324,9 @@ pandas 0.12
(:issue:`4145`, :issue:`4146`)
- Fixed bug in the parsing of microseconds when using the ``format``
argument in ``to_datetime`` (:issue:`4152`)
- Fixed bug in ``Series.where`` where broadcasting a single element input vector
to the length of the series resulted in multiplying the value
inside the input (:issue:`4192`)

pandas 0.11.0
=============
Expand Down
8 changes: 6 additions & 2 deletions pandas/core/series.py
Original file line number Diff line number Diff line change
Expand Up @@ -751,11 +751,12 @@ def where(self, cond, other=nan, inplace=False):

if len(other) != len(ser):
icond = ~cond

print "First", other
# GH 2745
# treat like a scalar
if len(other) == 1:
other = np.array(other[0]*len(ser))
other = np.array(other[0])
print "EQ 1", other

# GH 3235
# match True cond to other
Expand All @@ -767,7 +768,10 @@ def where(self, cond, other=nan, inplace=False):
other = new_other

else:
print "Raising", other
raise ValueError('Length of replacements must equal series length')

print "Finished", other

change = ser if inplace else None
com._maybe_upcast_putmask(ser,~cond,other,change=change)
Expand Down
23 changes: 18 additions & 5 deletions pandas/tests/test_series.py
Original file line number Diff line number Diff line change
Expand Up @@ -1090,11 +1090,6 @@ def test_where(self):
expected = Series([0,2])
assert_series_equal(s,expected)

s = Series([1,2])
s[[True, False]] = [0]
expected = Series([0,2])
assert_series_equal(s,expected)

# failures
self.assertRaises(ValueError, s.__setitem__, tuple([[[True, False]]]), [0,2,3])
self.assertRaises(ValueError, s.__setitem__, tuple([[[True, False]]]), [])
Expand Down Expand Up @@ -1142,6 +1137,24 @@ def test_where(self):
s = Series(np.arange(10))
mask = s > 5
self.assertRaises(ValueError, s.__setitem__, mask, ([0]*5,))

def test_where_broadcast(self):
# Test a variety of differently sized series
for size in range(2, 6):
# Test a variety of boolean indices
for selection in [np.resize([True, False, False, False, False], size), # First element should be set
np.resize([True, False], size), # Set alternating elements]
np.resize([False], size)]: # No element should be set
# Test a variety of different numbers as content
for item in [2.0, np.nan, np.finfo(np.float).max, np.finfo(np.float).min]:
# Test numpy arrays, lists and tuples as the input to be broadcast
for arr in [np.array([item]), [item], (item,)]:
data = np.arange(size, dtype=float)
s = Series(data)
s[selection] = arr
# Construct the expected series by taking the source data or item based on the selection
expected = Series([item if use_item else data[i] for i, use_item in enumerate(selection)])
assert_series_equal(s,expected)

def test_where_inplace(self):
s = Series(np.random.randn(5))
Expand Down