Skip to content

Commit b74b2dd

Browse files
jrebackwesm
authored andcommitted
ENH: added neg/inv operators to series
fixed setitem with boolean indexer to accept an object needing alignment (e.g. a partial series)
1 parent 928d431 commit b74b2dd

File tree

2 files changed

+36
-9
lines changed

2 files changed

+36
-9
lines changed

pandas/core/series.py

Lines changed: 22 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -616,6 +616,9 @@ def where(self, cond, other=nan, inplace=False):
616616
if len(cond) != len(self):
617617
raise ValueError('condition must have same length as series')
618618

619+
if not cond.dtype == np.bool_:
620+
cond = cond.astype(np.bool_)
621+
619622
ser = self if inplace else self.copy()
620623
if not isinstance(other, (list, tuple, np.ndarray)):
621624
ser._set_with(~cond, other)
@@ -672,10 +675,11 @@ def __setitem__(self, key, value):
672675
# Could not hash item
673676

674677
if _is_bool_indexer(key):
678+
#import pdb; pdb.set_
675679
key = self._check_bool_indexer(key)
676-
key = np.asarray(key, dtype=bool)
677-
678-
self._set_with(key, value)
680+
self.where(~key,value,inplace=True)
681+
else:
682+
self._set_with(key, value)
679683

680684
def _set_with(self, key, value):
681685
# other: fancy integer or otherwise
@@ -707,13 +711,7 @@ def _set_with(self, key, value):
707711
else:
708712
return self._set_values(key, value)
709713
elif key_type == 'boolean':
710-
711-
# scalar setting with boolean key
712-
if np.isscalar(value):
713714
self._set_values(key, value)
714-
# we have a key mask and a value that is np.array like
715-
else:
716-
np.putmask(self.values, key, value)
717715
else:
718716
self._set_labels(key, value)
719717

@@ -758,6 +756,12 @@ def _check_bool_indexer(self, key):
758756
raise ValueError('cannot index with vector containing '
759757
'NA / NaN values')
760758

759+
# coerce to bool type
760+
if not hasattr(result, 'shape'):
761+
result = np.array(result)
762+
if not result.dtype == np.bool_:
763+
result = result.astype(np.bool_)
764+
761765
return result
762766

763767
def __setslice__(self, i, j, value):
@@ -1115,6 +1119,15 @@ def iteritems(self):
11151119
__le__ = _comp_method(operator.le, '__le__')
11161120
__eq__ = _comp_method(operator.eq, '__eq__')
11171121
__ne__ = _comp_method(operator.ne, '__ne__')
1122+
1123+
# inversion
1124+
def __neg__(self):
1125+
arr = operator.neg(self.values)
1126+
return Series(arr, self.index, name=self.name)
1127+
1128+
def __invert__(self):
1129+
arr = operator.inv(self.values)
1130+
return Series(arr, self.index, name=self.name)
11181131

11191132
# binary logic
11201133
__or__ = _bool_method(operator.or_, '__or__')

pandas/tests/test_series.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1047,11 +1047,19 @@ def test_ix_setitem(self):
10471047
def test_setitem_boolean(self):
10481048
mask = self.series > self.series.median()
10491049

1050+
# similiar indexed series
10501051
result = self.series.copy()
10511052
result[mask] = self.series*2
10521053
expected = self.series*2
10531054
assert_series_equal(result[mask], expected[mask])
10541055

1056+
# needs alignment
1057+
result = self.series.copy()
1058+
result[mask] = (self.series*2)[0:5]
1059+
expected = (self.series*2)[0:5].reindex_like(self.series)
1060+
expected[-mask] = self.series[mask]
1061+
assert_series_equal(result[mask], expected[mask])
1062+
10551063
def test_ix_setitem_boolean(self):
10561064
mask = self.series > self.series.median()
10571065

@@ -1525,6 +1533,12 @@ def check(series, other):
15251533
check(self.ts, self.ts[::2])
15261534
check(self.ts, 5)
15271535

1536+
def test_neg(self):
1537+
assert_series_equal(-self.series, -1 * self.series)
1538+
1539+
def test_invert(self):
1540+
assert_series_equal(-(self.series < 0), ~(self.series < 0))
1541+
15281542
def test_operators(self):
15291543

15301544
def _check_op(series, other, op, pos_only=False):

0 commit comments

Comments
 (0)