From 7e715019d92bedf3093ef1fb075b6da5fe70d659 Mon Sep 17 00:00:00 2001 From: wuisawesome Date: Sun, 23 Apr 2017 23:40:08 -0700 Subject: [PATCH 1/6] ENH: Unary plus operator, deals with issue #16073 Overrides `+` operator, providing consistent behavior with `-`. Creates tests for the new operator for series and dataframes. --- pandas/core/generic.py | 8 ++++++++ pandas/tests/frame/test_operators.py | 3 +++ pandas/tests/series/test_operators.py | 3 +++ 3 files changed, 14 insertions(+) diff --git a/pandas/core/generic.py b/pandas/core/generic.py index 74d3053821e39..70db6269dda46 100644 --- a/pandas/core/generic.py +++ b/pandas/core/generic.py @@ -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_: + 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_: diff --git a/pandas/tests/frame/test_operators.py b/pandas/tests/frame/test_operators.py index 18639990662b0..ffd6c294cec06 100644 --- a/pandas/tests/frame/test_operators.py +++ b/pandas/tests/frame/test_operators.py @@ -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) diff --git a/pandas/tests/series/test_operators.py b/pandas/tests/series/test_operators.py index 159b29aca1e7c..0802662786e29 100644 --- a/pandas/tests/series/test_operators.py +++ b/pandas/tests/series/test_operators.py @@ -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 + def test_neg(self): assert_series_equal(-self.series, -1 * self.series) From af7512a5c64ddaaf2273097c9c7a31f0124f0d7f Mon Sep 17 00:00:00 2001 From: wuisawesome Date: Mon, 24 Apr 2017 00:15:05 -0700 Subject: [PATCH 2/6] What's new --- doc/source/whatsnew/v0.20.0.txt | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/doc/source/whatsnew/v0.20.0.txt b/doc/source/whatsnew/v0.20.0.txt index 945922b5f9ba8..0fe78ae0e71da 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: From 38d48c84f16abdfd17e468868706c92110607c24 Mon Sep 17 00:00:00 2001 From: wuisawesome Date: Sun, 23 Apr 2017 23:40:08 -0700 Subject: [PATCH 3/6] ENH: Unary plus operator, deals with issue #16073 Overrides `+` operator, providing consistent behavior with `-`. Creates tests for the new operator for series and dataframes. Edits "What's new" to reflect the new feature --- doc/source/whatsnew/v0.20.0.txt | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/doc/source/whatsnew/v0.20.0.txt b/doc/source/whatsnew/v0.20.0.txt index 945922b5f9ba8..0fe78ae0e71da 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: From f10e3be39a282e85b85ce480ff8de48fda27267b Mon Sep 17 00:00:00 2001 From: wuisawesome Date: Sun, 23 Apr 2017 23:40:08 -0700 Subject: [PATCH 4/6] ENH: Unary plus operator, deals with issue #16073 Overrides `+` operator, providing consistent behavior with `-`. Creates tests for the new operator for series and dataframes. Edits "What's new" to reflect the new feature --- doc/source/whatsnew/v0.20.0.txt | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/doc/source/whatsnew/v0.20.0.txt b/doc/source/whatsnew/v0.20.0.txt index 945922b5f9ba8..0fe78ae0e71da 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: From 2c0962487fa030211455528090609bc74699a1a0 Mon Sep 17 00:00:00 2001 From: wuisawesome Date: Mon, 24 Apr 2017 11:37:05 -0700 Subject: [PATCH 5/6] Operator edge cases, better tests Updated plus operator edge case. Datatype that implement + but not - should not be able to use + to maintain symmetry Rewrites tests to work better with strings and other non numeric datatypes that implement `*` operator --- pandas/core/generic.py | 7 ++++++- pandas/tests/frame/test_operators.py | 9 ++++++--- pandas/tests/series/test_operators.py | 8 ++++++-- 3 files changed, 18 insertions(+), 6 deletions(-) diff --git a/pandas/core/generic.py b/pandas/core/generic.py index 70db6269dda46..a8548d46118f3 100644 --- a/pandas/core/generic.py +++ b/pandas/core/generic.py @@ -862,8 +862,13 @@ def _indexed_same(self, other): def __pos__(self): values = _values_from_object(self) if values.dtype == np.bool_: - arr = values #To remain consistent with __neg__ + 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) diff --git a/pandas/tests/frame/test_operators.py b/pandas/tests/frame/test_operators.py index ffd6c294cec06..c91b63cf9daee 100644 --- a/pandas/tests/frame/test_operators.py +++ b/pandas/tests/frame/test_operators.py @@ -344,11 +344,14 @@ def test_logical_with_nas(self): assert_series_equal(result, expected) def test_pos(self): - assert_frame_equal(+self.frame, 1 * self.frame) + 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 0802662786e29..a8319af88ec41 100644 --- a/pandas/tests/series/test_operators.py +++ b/pandas/tests/series/test_operators.py @@ -92,10 +92,14 @@ def check(series, other, check_reverse=False): check(tm.makeFloatSeries(), tm.makeFloatSeries(), check_reverse=True) def test_pos(self): - assert_series_equal(+self.series, 1 * self.series) #Ensures no rounding issues + 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)) From c658f7fe272499b4a8ea0956d8716e64eff3a7fb Mon Sep 17 00:00:00 2001 From: wuisawesome Date: Mon, 24 Apr 2017 11:41:31 -0700 Subject: [PATCH 6/6] Added double ticks to whats new --- doc/source/whatsnew/v0.20.0.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/source/whatsnew/v0.20.0.txt b/doc/source/whatsnew/v0.20.0.txt index 0fe78ae0e71da..4d2fcc5d2f755 100644 --- a/doc/source/whatsnew/v0.20.0.txt +++ b/doc/source/whatsnew/v0.20.0.txt @@ -1195,7 +1195,7 @@ 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. +- ``Series`` and ``DataFrame`` now have unary plus operators (:issue:`16073`). The plus operator behaves consistently with the unary minus operator. .. _whatsnew_0200.privacy: