Skip to content

Unary plus operator (Issue #16073) #16106

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

Closed
wants to merge 10 commits into from
5 changes: 3 additions & 2 deletions doc/source/whatsnew/v0.20.0.txt
Original file line number Diff line number Diff line change
Expand Up @@ -213,8 +213,7 @@ See :ref:`the docs here <io.pickle.compression>`

Using an explicit compression type

.. ipython:: python
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

don't change other things in the file

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not certain why this happened. The rest of the diff shows that the same identical line is added again, thus making no actual changes to the file


.. ipython:: python
df.to_pickle("data.pkl.compress", compression="gzip")
rt = pd.read_pickle("data.pkl.compress", compression="gzip")
rt
Expand Down Expand Up @@ -1196,6 +1195,8 @@ Other API Changes
- ``DataFrame`` and ``Panel`` constructors with invalid input will now raise ``ValueError`` rather than ``pandas.core.common.PandasError``, if called with scalar inputs and not axes; The exception ``PandasError`` is removed as well. (:issue:`15541`)
- The exception ``pandas.core.common.AmbiguousIndexError`` is removed as it is not referenced (:issue:`15541`)

- `Series` and `DataFrame` now have unary plus operators (:issue:`16073`). The plus operator behaves consistently with the unary minus operator.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

use double backticks here around Series, DataFrame. Put the issue reference at the end.



.. _whatsnew_0200.privacy:

Expand Down
8 changes: 8 additions & 0 deletions pandas/core/generic.py
Original file line number Diff line number Diff line change
Expand Up @@ -859,6 +859,14 @@ def _indexed_same(self, other):
return all([self._get_axis(a).equals(other._get_axis(a))
for a in self._AXIS_ORDERS])

def __pos__(self):
values = _values_from_object(self)
if values.dtype == np.bool_:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

something like:

if is_bool_dtype(values):
   ...
elif not (is_numeric_dtype(values) or is_timedelta64_dtype(values)):
   raise

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

add the same logic to __neg__

arr = values #To remain consistent with __neg__
else:
arr = operator.pos(values)
return self.__array_wrap__(arr)

def __neg__(self):
values = _values_from_object(self)
if values.dtype == np.bool_:
Expand Down
3 changes: 3 additions & 0 deletions pandas/tests/frame/test_operators.py
Original file line number Diff line number Diff line change
Expand Up @@ -343,6 +343,9 @@ def test_logical_with_nas(self):
expected = Series([True, True])
assert_series_equal(result, expected)

def test_pos(self):
assert_frame_equal(+self.frame, 1 * self.frame)

def test_neg(self):
# what to do?
assert_frame_equal(-self.frame, -1 * self.frame)
Expand Down
3 changes: 3 additions & 0 deletions pandas/tests/series/test_operators.py
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,9 @@ def check(series, other, check_reverse=False):
check(self.ts, 5, check_reverse=True)
check(tm.makeFloatSeries(), tm.makeFloatSeries(), check_reverse=True)

def test_pos(self):
assert_series_equal(+self.series, 1 * self.series) #Ensures no rounding issues
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

comment is not necessary


Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

add a couple of raise assertion on strings

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this would technically work on datetimes, but I think we should disallow this (pls add tests for __neg__ as well).

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

e.g.

In [9]: -Series(list('abc'))
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-9-93660e79330e> in <module>()
----> 1 -Series(list('abc'))

/Users/jreback/pandas/pandas/core/generic.py in __neg__(self)
    865             arr = operator.inv(values)
    866         else:
--> 867             arr = operator.neg(values)
    868         return self.__array_wrap__(arr)
    869 

TypeError: bad operand type for unary -: 'str'

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In [10]: Series(pd.date_range('20130101', periods=3))
Out[10]: 
0   2013-01-01
1   2013-01-02
2   2013-01-03
dtype: datetime64[ns]

In [11]: -Series(pd.date_range('20130101', periods=3))
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-11-23bfb90f61eb> in <module>()
----> 1 -Series(pd.date_range('20130101', periods=3))

/Users/jreback/pandas/pandas/core/generic.py in __neg__(self)
    865             arr = operator.inv(values)
    866         else:
--> 867             arr = operator.neg(values)
    868         return self.__array_wrap__(arr)
    869 

TypeError: ufunc 'negative' did not contain a loop with signature matching types dtype('<M8[ns]') dtype('<M8[ns]')

In [12]: +Series(pd.date_range('20130101', periods=3))
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-12-b72a11ca274c> in <module>()
----> 1 +Series(pd.date_range('20130101', periods=3))

TypeError: bad operand type for unary +: 'Series'

I want [12] still to raise after this change.

def test_neg(self):
assert_series_equal(-self.series, -1 * self.series)

Expand Down