diff --git a/doc/source/whatsnew/v1.0.0.rst b/doc/source/whatsnew/v1.0.0.rst index e1fe2f7fe77e2..e6272b2a97dc1 100644 --- a/doc/source/whatsnew/v1.0.0.rst +++ b/doc/source/whatsnew/v1.0.0.rst @@ -145,7 +145,7 @@ Indexing ^^^^^^^^ - Bug in assignment using a reverse slicer (:issue:`26939`) -- +- Bug in reindexing a :meth:`PeriodIndex` with another type of index that contained a `Period` (:issue:`28323`) (:issue:`28337`) Missing ^^^^^^^ @@ -214,7 +214,7 @@ Other - Trying to set the ``display.precision``, ``display.max_rows`` or ``display.max_columns`` using :meth:`set_option` to anything but a ``None`` or a positive int will raise a ``ValueError`` (:issue:`23348`) - Using :meth:`DataFrame.replace` with overlapping keys in a nested dictionary will no longer raise, now matching the behavior of a flat dictionary (:issue:`27660`) - :meth:`DataFrame.to_csv` and :meth:`Series.to_csv` now support dicts as ``compression`` argument with key ``'method'`` being the compression method and others as additional compression options when the compression method is ``'zip'``. (:issue:`26023`) - +- .. _whatsnew_1000.contributors: diff --git a/pandas/core/indexes/period.py b/pandas/core/indexes/period.py index f7bf77928bdc7..ee85b0fb91acb 100644 --- a/pandas/core/indexes/period.py +++ b/pandas/core/indexes/period.py @@ -651,10 +651,13 @@ def get_indexer(self, target, method=None, limit=None, tolerance=None): if isinstance(target, PeriodIndex): target = target.asi8 + self_index = self._int64index + else: + self_index = self if tolerance is not None: tolerance = self._convert_tolerance(tolerance, target) - return Index.get_indexer(self._int64index, target, method, limit, tolerance) + return Index.get_indexer(self_index, target, method, limit, tolerance) @Appender(_index_shared_docs["get_indexer_non_unique"] % _index_doc_kwargs) def get_indexer_non_unique(self, target): diff --git a/pandas/tests/indexes/period/test_period.py b/pandas/tests/indexes/period/test_period.py index 8b3b66bd1ee6b..ee37be7ab4c14 100644 --- a/pandas/tests/indexes/period/test_period.py +++ b/pandas/tests/indexes/period/test_period.py @@ -354,6 +354,35 @@ def test_period_set_index_reindex(self): df = df.set_index(idx2) tm.assert_index_equal(df.index, idx2) + @pytest.mark.parametrize( + "p_values, o_values, values, expected_values", + [ + ( + [Period("2019Q1", "Q-DEC"), Period("2019Q2", "Q-DEC")], + [Period("2019Q1", "Q-DEC"), Period("2019Q2", "Q-DEC"), "All"], + [1.0, 1.0], + [1.0, 1.0, np.nan], + ), + ( + [Period("2019Q1", "Q-DEC"), Period("2019Q2", "Q-DEC")], + [Period("2019Q1", "Q-DEC"), Period("2019Q2", "Q-DEC")], + [1.0, 1.0], + [1.0, 1.0], + ), + ], + ) + def test_period_reindex_with_object( + self, p_values, o_values, values, expected_values + ): + # GH 28337 + period_index = PeriodIndex(p_values) + object_index = Index(o_values) + + s = pd.Series(values, index=period_index) + result = s.reindex(object_index) + expected = pd.Series(expected_values, index=object_index) + tm.assert_series_equal(result, expected) + def test_factorize(self): idx1 = PeriodIndex( ["2014-01", "2014-01", "2014-02", "2014-02", "2014-03", "2014-03"], freq="M" diff --git a/pandas/tests/reshape/test_pivot.py b/pandas/tests/reshape/test_pivot.py index 03b15d2df1a26..582084e3bfb5a 100644 --- a/pandas/tests/reshape/test_pivot.py +++ b/pandas/tests/reshape/test_pivot.py @@ -677,6 +677,32 @@ def test_pivot_periods(self, method): pv = pd.pivot(df, index="p1", columns="p2", values="data1") tm.assert_frame_equal(pv, expected) + def test_pivot_periods_with_margins(self): + # GH 28323 + df = DataFrame( + { + "a": [1, 1, 2, 2], + "b": [ + pd.Period("2019Q1"), + pd.Period("2019Q2"), + pd.Period("2019Q1"), + pd.Period("2019Q2"), + ], + "x": 1.0, + } + ) + + expected = DataFrame( + data=1.0, + index=pd.Index([1, 2, "All"], name="a"), + columns=pd.Index( + [pd.Period("2019Q1"), pd.Period("2019Q2"), "All"], name="b" + ), + ) + + result = df.pivot_table(index="a", columns="b", values="x", margins=True) + tm.assert_frame_equal(expected, result) + @pytest.mark.parametrize( "values", [