diff --git a/doc/source/whatsnew/v0.20.0.txt b/doc/source/whatsnew/v0.20.0.txt index 945922b5f9ba8..4d2fcc5d2f755 100644 --- a/doc/source/whatsnew/v0.20.0.txt +++ b/doc/source/whatsnew/v0.20.0.txt @@ -213,8 +213,7 @@ See :ref:`the docs here ` Using an explicit compression type -.. ipython:: python - +.. ipython:: python df.to_pickle("data.pkl.compress", compression="gzip") rt = pd.read_pickle("data.pkl.compress", compression="gzip") rt @@ -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. + .. _whatsnew_0200.privacy: diff --git a/pandas/core/generic.py b/pandas/core/generic.py index 74d3053821e39..a8548d46118f3 100644 --- a/pandas/core/generic.py +++ b/pandas/core/generic.py @@ -859,6 +859,19 @@ 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_: + arr = values + else: + if (len(values) > 0): + try: + -values[0] + except TypeError: + raise TypeError("`+` only works on data types that support `-`") + arr = operator.pos(values) + return self.__array_wrap__(arr) + def __neg__(self): values = _values_from_object(self) if values.dtype == np.bool_: diff --git a/pandas/tests/frame/test_operators.py b/pandas/tests/frame/test_operators.py index 3f77bc754a525..223142838fbcb 100644 --- a/pandas/tests/frame/test_operators.py +++ b/pandas/tests/frame/test_operators.py @@ -343,9 +343,15 @@ def test_logical_with_nas(self): expected = Series([True, True]) assert_series_equal(result, expected) + def test_pos(self): + try: + assert_frame_equal(+self.frame, self.frame.apply(lambda x: +self.frame)) + except TypeError: + if not (len(self.frame) > 0 and isinstance(self.frame[0], pd.Timestamp)): + raise + def test_neg(self): - # what to do? - assert_frame_equal(-self.frame, -1 * self.frame) + assert_frame_equal(-self.frame, self.frame.apply(lambda x: -self.frame)) def test_invert(self): assert_frame_equal(-(self.frame < 0), ~(self.frame < 0)) diff --git a/pandas/tests/series/test_operators.py b/pandas/tests/series/test_operators.py index 159b29aca1e7c..a8319af88ec41 100644 --- a/pandas/tests/series/test_operators.py +++ b/pandas/tests/series/test_operators.py @@ -91,8 +91,15 @@ 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): + try: + assert_series_equal(+self.series, self.series.apply(lambda x: +x)) + except TypeError: + if not (len(self.frame) > 0 and isinstance(self.frame[0], pd.Timestampe)): + raise + def test_neg(self): - assert_series_equal(-self.series, -1 * self.series) + assert_series_equal(-self.series, self.series.apply(lambda x: -x)) def test_invert(self): assert_series_equal(-(self.series < 0), ~(self.series < 0))