done
This commit is contained in:
		| @ -0,0 +1,189 @@ | ||||
| import re | ||||
|  | ||||
| import pytest | ||||
|  | ||||
| from pandas import ( | ||||
|     PeriodIndex, | ||||
|     Series, | ||||
|     period_range, | ||||
| ) | ||||
| import pandas._testing as tm | ||||
|  | ||||
| from pandas.tseries import offsets | ||||
|  | ||||
|  | ||||
| class TestPeriodIndex: | ||||
|     def test_asfreq(self): | ||||
|         pi1 = period_range(freq="Y", start="1/1/2001", end="1/1/2001") | ||||
|         pi2 = period_range(freq="Q", start="1/1/2001", end="1/1/2001") | ||||
|         pi3 = period_range(freq="M", start="1/1/2001", end="1/1/2001") | ||||
|         pi4 = period_range(freq="D", start="1/1/2001", end="1/1/2001") | ||||
|         pi5 = period_range(freq="h", start="1/1/2001", end="1/1/2001 00:00") | ||||
|         pi6 = period_range(freq="Min", start="1/1/2001", end="1/1/2001 00:00") | ||||
|         pi7 = period_range(freq="s", start="1/1/2001", end="1/1/2001 00:00:00") | ||||
|  | ||||
|         assert pi1.asfreq("Q", "s") == pi2 | ||||
|         assert pi1.asfreq("Q", "s") == pi2 | ||||
|         assert pi1.asfreq("M", "start") == pi3 | ||||
|         assert pi1.asfreq("D", "StarT") == pi4 | ||||
|         assert pi1.asfreq("h", "beGIN") == pi5 | ||||
|         assert pi1.asfreq("Min", "s") == pi6 | ||||
|         assert pi1.asfreq("s", "s") == pi7 | ||||
|  | ||||
|         assert pi2.asfreq("Y", "s") == pi1 | ||||
|         assert pi2.asfreq("M", "s") == pi3 | ||||
|         assert pi2.asfreq("D", "s") == pi4 | ||||
|         assert pi2.asfreq("h", "s") == pi5 | ||||
|         assert pi2.asfreq("Min", "s") == pi6 | ||||
|         assert pi2.asfreq("s", "s") == pi7 | ||||
|  | ||||
|         assert pi3.asfreq("Y", "s") == pi1 | ||||
|         assert pi3.asfreq("Q", "s") == pi2 | ||||
|         assert pi3.asfreq("D", "s") == pi4 | ||||
|         assert pi3.asfreq("h", "s") == pi5 | ||||
|         assert pi3.asfreq("Min", "s") == pi6 | ||||
|         assert pi3.asfreq("s", "s") == pi7 | ||||
|  | ||||
|         assert pi4.asfreq("Y", "s") == pi1 | ||||
|         assert pi4.asfreq("Q", "s") == pi2 | ||||
|         assert pi4.asfreq("M", "s") == pi3 | ||||
|         assert pi4.asfreq("h", "s") == pi5 | ||||
|         assert pi4.asfreq("Min", "s") == pi6 | ||||
|         assert pi4.asfreq("s", "s") == pi7 | ||||
|  | ||||
|         assert pi5.asfreq("Y", "s") == pi1 | ||||
|         assert pi5.asfreq("Q", "s") == pi2 | ||||
|         assert pi5.asfreq("M", "s") == pi3 | ||||
|         assert pi5.asfreq("D", "s") == pi4 | ||||
|         assert pi5.asfreq("Min", "s") == pi6 | ||||
|         assert pi5.asfreq("s", "s") == pi7 | ||||
|  | ||||
|         assert pi6.asfreq("Y", "s") == pi1 | ||||
|         assert pi6.asfreq("Q", "s") == pi2 | ||||
|         assert pi6.asfreq("M", "s") == pi3 | ||||
|         assert pi6.asfreq("D", "s") == pi4 | ||||
|         assert pi6.asfreq("h", "s") == pi5 | ||||
|         assert pi6.asfreq("s", "s") == pi7 | ||||
|  | ||||
|         assert pi7.asfreq("Y", "s") == pi1 | ||||
|         assert pi7.asfreq("Q", "s") == pi2 | ||||
|         assert pi7.asfreq("M", "s") == pi3 | ||||
|         assert pi7.asfreq("D", "s") == pi4 | ||||
|         assert pi7.asfreq("h", "s") == pi5 | ||||
|         assert pi7.asfreq("Min", "s") == pi6 | ||||
|  | ||||
|         msg = "How must be one of S or E" | ||||
|         with pytest.raises(ValueError, match=msg): | ||||
|             pi7.asfreq("T", "foo") | ||||
|         result1 = pi1.asfreq("3M") | ||||
|         result2 = pi1.asfreq("M") | ||||
|         expected = period_range(freq="M", start="2001-12", end="2001-12") | ||||
|         tm.assert_numpy_array_equal(result1.asi8, expected.asi8) | ||||
|         assert result1.freqstr == "3M" | ||||
|         tm.assert_numpy_array_equal(result2.asi8, expected.asi8) | ||||
|         assert result2.freqstr == "M" | ||||
|  | ||||
|     def test_asfreq_nat(self): | ||||
|         idx = PeriodIndex(["2011-01", "2011-02", "NaT", "2011-04"], freq="M") | ||||
|         result = idx.asfreq(freq="Q") | ||||
|         expected = PeriodIndex(["2011Q1", "2011Q1", "NaT", "2011Q2"], freq="Q") | ||||
|         tm.assert_index_equal(result, expected) | ||||
|  | ||||
|     @pytest.mark.parametrize("freq", ["D", "3D"]) | ||||
|     def test_asfreq_mult_pi(self, freq): | ||||
|         pi = PeriodIndex(["2001-01", "2001-02", "NaT", "2001-03"], freq="2M") | ||||
|  | ||||
|         result = pi.asfreq(freq) | ||||
|         exp = PeriodIndex(["2001-02-28", "2001-03-31", "NaT", "2001-04-30"], freq=freq) | ||||
|         tm.assert_index_equal(result, exp) | ||||
|         assert result.freq == exp.freq | ||||
|  | ||||
|         result = pi.asfreq(freq, how="S") | ||||
|         exp = PeriodIndex(["2001-01-01", "2001-02-01", "NaT", "2001-03-01"], freq=freq) | ||||
|         tm.assert_index_equal(result, exp) | ||||
|         assert result.freq == exp.freq | ||||
|  | ||||
|     def test_asfreq_combined_pi(self): | ||||
|         pi = PeriodIndex(["2001-01-01 00:00", "2001-01-02 02:00", "NaT"], freq="h") | ||||
|         exp = PeriodIndex(["2001-01-01 00:00", "2001-01-02 02:00", "NaT"], freq="25h") | ||||
|         for freq, how in zip(["1D1h", "1h1D"], ["S", "E"]): | ||||
|             result = pi.asfreq(freq, how=how) | ||||
|             tm.assert_index_equal(result, exp) | ||||
|             assert result.freq == exp.freq | ||||
|  | ||||
|         for freq in ["1D1h", "1h1D"]: | ||||
|             pi = PeriodIndex(["2001-01-01 00:00", "2001-01-02 02:00", "NaT"], freq=freq) | ||||
|             result = pi.asfreq("h") | ||||
|             exp = PeriodIndex(["2001-01-02 00:00", "2001-01-03 02:00", "NaT"], freq="h") | ||||
|             tm.assert_index_equal(result, exp) | ||||
|             assert result.freq == exp.freq | ||||
|  | ||||
|             pi = PeriodIndex(["2001-01-01 00:00", "2001-01-02 02:00", "NaT"], freq=freq) | ||||
|             result = pi.asfreq("h", how="S") | ||||
|             exp = PeriodIndex(["2001-01-01 00:00", "2001-01-02 02:00", "NaT"], freq="h") | ||||
|             tm.assert_index_equal(result, exp) | ||||
|             assert result.freq == exp.freq | ||||
|  | ||||
|     def test_astype_asfreq(self): | ||||
|         pi1 = PeriodIndex(["2011-01-01", "2011-02-01", "2011-03-01"], freq="D") | ||||
|         exp = PeriodIndex(["2011-01", "2011-02", "2011-03"], freq="M") | ||||
|         tm.assert_index_equal(pi1.asfreq("M"), exp) | ||||
|         tm.assert_index_equal(pi1.astype("period[M]"), exp) | ||||
|  | ||||
|         exp = PeriodIndex(["2011-01", "2011-02", "2011-03"], freq="3M") | ||||
|         tm.assert_index_equal(pi1.asfreq("3M"), exp) | ||||
|         tm.assert_index_equal(pi1.astype("period[3M]"), exp) | ||||
|  | ||||
|     def test_asfreq_with_different_n(self): | ||||
|         ser = Series([1, 2], index=PeriodIndex(["2020-01", "2020-03"], freq="2M")) | ||||
|         result = ser.asfreq("M") | ||||
|  | ||||
|         excepted = Series([1, 2], index=PeriodIndex(["2020-02", "2020-04"], freq="M")) | ||||
|         tm.assert_series_equal(result, excepted) | ||||
|  | ||||
|     @pytest.mark.parametrize( | ||||
|         "freq", | ||||
|         [ | ||||
|             "2BMS", | ||||
|             "2YS-MAR", | ||||
|             "2bh", | ||||
|         ], | ||||
|     ) | ||||
|     def test_pi_asfreq_not_supported_frequency(self, freq): | ||||
|         # GH#55785 | ||||
|         msg = f"{freq[1:]} is not supported as period frequency" | ||||
|  | ||||
|         pi = PeriodIndex(["2020-01-01", "2021-01-01"], freq="M") | ||||
|         with pytest.raises(ValueError, match=msg): | ||||
|             pi.asfreq(freq=freq) | ||||
|  | ||||
|     @pytest.mark.parametrize( | ||||
|         "freq", | ||||
|         [ | ||||
|             "2BME", | ||||
|             "2YE-MAR", | ||||
|             "2QE", | ||||
|         ], | ||||
|     ) | ||||
|     def test_pi_asfreq_invalid_frequency(self, freq): | ||||
|         # GH#55785 | ||||
|         msg = f"Invalid frequency: {freq}" | ||||
|  | ||||
|         pi = PeriodIndex(["2020-01-01", "2021-01-01"], freq="M") | ||||
|         with pytest.raises(ValueError, match=msg): | ||||
|             pi.asfreq(freq=freq) | ||||
|  | ||||
|     @pytest.mark.parametrize( | ||||
|         "freq", | ||||
|         [ | ||||
|             offsets.MonthBegin(2), | ||||
|             offsets.BusinessMonthEnd(2), | ||||
|         ], | ||||
|     ) | ||||
|     def test_pi_asfreq_invalid_baseoffset(self, freq): | ||||
|         # GH#56945 | ||||
|         msg = re.escape(f"{freq} is not supported as period frequency") | ||||
|  | ||||
|         pi = PeriodIndex(["2020-01-01", "2021-01-01"], freq="M") | ||||
|         with pytest.raises(ValueError, match=msg): | ||||
|             pi.asfreq(freq=freq) | ||||
| @ -0,0 +1,156 @@ | ||||
| import numpy as np | ||||
| import pytest | ||||
|  | ||||
| from pandas import ( | ||||
|     CategoricalIndex, | ||||
|     DatetimeIndex, | ||||
|     Index, | ||||
|     NaT, | ||||
|     Period, | ||||
|     PeriodIndex, | ||||
|     period_range, | ||||
| ) | ||||
| import pandas._testing as tm | ||||
|  | ||||
|  | ||||
| class TestPeriodIndexAsType: | ||||
|     @pytest.mark.parametrize("dtype", [float, "timedelta64", "timedelta64[ns]"]) | ||||
|     def test_astype_raises(self, dtype): | ||||
|         # GH#13149, GH#13209 | ||||
|         idx = PeriodIndex(["2016-05-16", "NaT", NaT, np.nan], freq="D") | ||||
|         msg = "Cannot cast PeriodIndex to dtype" | ||||
|         with pytest.raises(TypeError, match=msg): | ||||
|             idx.astype(dtype) | ||||
|  | ||||
|     def test_astype_conversion(self, using_infer_string): | ||||
|         # GH#13149, GH#13209 | ||||
|         idx = PeriodIndex(["2016-05-16", "NaT", NaT, np.nan], freq="D", name="idx") | ||||
|  | ||||
|         result = idx.astype(object) | ||||
|         expected = Index( | ||||
|             [Period("2016-05-16", freq="D")] + [Period(NaT, freq="D")] * 3, | ||||
|             dtype="object", | ||||
|             name="idx", | ||||
|         ) | ||||
|         tm.assert_index_equal(result, expected) | ||||
|  | ||||
|         result = idx.astype(np.int64) | ||||
|         expected = Index( | ||||
|             [16937] + [-9223372036854775808] * 3, dtype=np.int64, name="idx" | ||||
|         ) | ||||
|         tm.assert_index_equal(result, expected) | ||||
|  | ||||
|         result = idx.astype(str) | ||||
|         if using_infer_string: | ||||
|             expected = Index( | ||||
|                 [str(x) if x is not NaT else None for x in idx], name="idx", dtype="str" | ||||
|             ) | ||||
|         else: | ||||
|             expected = Index([str(x) for x in idx], name="idx", dtype=object) | ||||
|         tm.assert_index_equal(result, expected) | ||||
|  | ||||
|         idx = period_range("1990", "2009", freq="Y", name="idx") | ||||
|         result = idx.astype("i8") | ||||
|         tm.assert_index_equal(result, Index(idx.asi8, name="idx")) | ||||
|         tm.assert_numpy_array_equal(result.values, idx.asi8) | ||||
|  | ||||
|     def test_astype_uint(self): | ||||
|         arr = period_range("2000", periods=2, name="idx") | ||||
|  | ||||
|         with pytest.raises(TypeError, match=r"Do obj.astype\('int64'\)"): | ||||
|             arr.astype("uint64") | ||||
|         with pytest.raises(TypeError, match=r"Do obj.astype\('int64'\)"): | ||||
|             arr.astype("uint32") | ||||
|  | ||||
|     def test_astype_object(self): | ||||
|         idx = PeriodIndex([], freq="M") | ||||
|  | ||||
|         exp = np.array([], dtype=object) | ||||
|         tm.assert_numpy_array_equal(idx.astype(object).values, exp) | ||||
|         tm.assert_numpy_array_equal(idx._mpl_repr(), exp) | ||||
|  | ||||
|         idx = PeriodIndex(["2011-01", NaT], freq="M") | ||||
|  | ||||
|         exp = np.array([Period("2011-01", freq="M"), NaT], dtype=object) | ||||
|         tm.assert_numpy_array_equal(idx.astype(object).values, exp) | ||||
|         tm.assert_numpy_array_equal(idx._mpl_repr(), exp) | ||||
|  | ||||
|         exp = np.array([Period("2011-01-01", freq="D"), NaT], dtype=object) | ||||
|         idx = PeriodIndex(["2011-01-01", NaT], freq="D") | ||||
|         tm.assert_numpy_array_equal(idx.astype(object).values, exp) | ||||
|         tm.assert_numpy_array_equal(idx._mpl_repr(), exp) | ||||
|  | ||||
|     # TODO: de-duplicate this version (from test_ops) with the one above | ||||
|     # (from test_period) | ||||
|     def test_astype_object2(self): | ||||
|         idx = period_range(start="2013-01-01", periods=4, freq="M", name="idx") | ||||
|         expected_list = [ | ||||
|             Period("2013-01-31", freq="M"), | ||||
|             Period("2013-02-28", freq="M"), | ||||
|             Period("2013-03-31", freq="M"), | ||||
|             Period("2013-04-30", freq="M"), | ||||
|         ] | ||||
|         expected = Index(expected_list, dtype=object, name="idx") | ||||
|         result = idx.astype(object) | ||||
|         assert isinstance(result, Index) | ||||
|         assert result.dtype == object | ||||
|         tm.assert_index_equal(result, expected) | ||||
|         assert result.name == expected.name | ||||
|         assert idx.tolist() == expected_list | ||||
|  | ||||
|         idx = PeriodIndex( | ||||
|             ["2013-01-01", "2013-01-02", "NaT", "2013-01-04"], freq="D", name="idx" | ||||
|         ) | ||||
|         expected_list = [ | ||||
|             Period("2013-01-01", freq="D"), | ||||
|             Period("2013-01-02", freq="D"), | ||||
|             Period("NaT", freq="D"), | ||||
|             Period("2013-01-04", freq="D"), | ||||
|         ] | ||||
|         expected = Index(expected_list, dtype=object, name="idx") | ||||
|         result = idx.astype(object) | ||||
|         assert isinstance(result, Index) | ||||
|         assert result.dtype == object | ||||
|         tm.assert_index_equal(result, expected) | ||||
|         for i in [0, 1, 3]: | ||||
|             assert result[i] == expected[i] | ||||
|         assert result[2] is NaT | ||||
|         assert result.name == expected.name | ||||
|  | ||||
|         result_list = idx.tolist() | ||||
|         for i in [0, 1, 3]: | ||||
|             assert result_list[i] == expected_list[i] | ||||
|         assert result_list[2] is NaT | ||||
|  | ||||
|     def test_astype_category(self): | ||||
|         obj = period_range("2000", periods=2, name="idx") | ||||
|         result = obj.astype("category") | ||||
|         expected = CategoricalIndex( | ||||
|             [Period("2000-01-01", freq="D"), Period("2000-01-02", freq="D")], name="idx" | ||||
|         ) | ||||
|         tm.assert_index_equal(result, expected) | ||||
|  | ||||
|         result = obj._data.astype("category") | ||||
|         expected = expected.values | ||||
|         tm.assert_categorical_equal(result, expected) | ||||
|  | ||||
|     def test_astype_array_fallback(self): | ||||
|         obj = period_range("2000", periods=2, name="idx") | ||||
|         result = obj.astype(bool) | ||||
|         expected = Index(np.array([True, True]), name="idx") | ||||
|         tm.assert_index_equal(result, expected) | ||||
|  | ||||
|         result = obj._data.astype(bool) | ||||
|         expected = np.array([True, True]) | ||||
|         tm.assert_numpy_array_equal(result, expected) | ||||
|  | ||||
|     def test_period_astype_to_timestamp(self, unit): | ||||
|         # GH#55958 | ||||
|         pi = PeriodIndex(["2011-01", "2011-02", "2011-03"], freq="M") | ||||
|  | ||||
|         exp = DatetimeIndex( | ||||
|             ["2011-01-01", "2011-02-01", "2011-03-01"], tz="US/Eastern" | ||||
|         ).as_unit(unit) | ||||
|         res = pi.astype(f"datetime64[{unit}, US/Eastern]") | ||||
|         tm.assert_index_equal(res, exp) | ||||
|         assert res.freq == exp.freq | ||||
| @ -0,0 +1,41 @@ | ||||
| import numpy as np | ||||
|  | ||||
| from pandas import PeriodIndex | ||||
| import pandas._testing as tm | ||||
|  | ||||
|  | ||||
| class TestFactorize: | ||||
|     def test_factorize_period(self): | ||||
|         idx1 = PeriodIndex( | ||||
|             ["2014-01", "2014-01", "2014-02", "2014-02", "2014-03", "2014-03"], | ||||
|             freq="M", | ||||
|         ) | ||||
|  | ||||
|         exp_arr = np.array([0, 0, 1, 1, 2, 2], dtype=np.intp) | ||||
|         exp_idx = PeriodIndex(["2014-01", "2014-02", "2014-03"], freq="M") | ||||
|  | ||||
|         arr, idx = idx1.factorize() | ||||
|         tm.assert_numpy_array_equal(arr, exp_arr) | ||||
|         tm.assert_index_equal(idx, exp_idx) | ||||
|  | ||||
|         arr, idx = idx1.factorize(sort=True) | ||||
|         tm.assert_numpy_array_equal(arr, exp_arr) | ||||
|         tm.assert_index_equal(idx, exp_idx) | ||||
|  | ||||
|     def test_factorize_period_nonmonotonic(self): | ||||
|         idx2 = PeriodIndex( | ||||
|             ["2014-03", "2014-03", "2014-02", "2014-01", "2014-03", "2014-01"], | ||||
|             freq="M", | ||||
|         ) | ||||
|         exp_idx = PeriodIndex(["2014-01", "2014-02", "2014-03"], freq="M") | ||||
|  | ||||
|         exp_arr = np.array([2, 2, 1, 0, 2, 0], dtype=np.intp) | ||||
|         arr, idx = idx2.factorize(sort=True) | ||||
|         tm.assert_numpy_array_equal(arr, exp_arr) | ||||
|         tm.assert_index_equal(idx, exp_idx) | ||||
|  | ||||
|         exp_arr = np.array([0, 0, 1, 2, 0, 2], dtype=np.intp) | ||||
|         exp_idx = PeriodIndex(["2014-03", "2014-02", "2014-01"], freq="M") | ||||
|         arr, idx = idx2.factorize() | ||||
|         tm.assert_numpy_array_equal(arr, exp_arr) | ||||
|         tm.assert_index_equal(idx, exp_idx) | ||||
| @ -0,0 +1,41 @@ | ||||
| from pandas import ( | ||||
|     Index, | ||||
|     NaT, | ||||
|     Period, | ||||
|     PeriodIndex, | ||||
| ) | ||||
| import pandas._testing as tm | ||||
|  | ||||
|  | ||||
| class TestFillNA: | ||||
|     def test_fillna_period(self): | ||||
|         # GH#11343 | ||||
|         idx = PeriodIndex(["2011-01-01 09:00", NaT, "2011-01-01 11:00"], freq="h") | ||||
|  | ||||
|         exp = PeriodIndex( | ||||
|             ["2011-01-01 09:00", "2011-01-01 10:00", "2011-01-01 11:00"], freq="h" | ||||
|         ) | ||||
|         result = idx.fillna(Period("2011-01-01 10:00", freq="h")) | ||||
|         tm.assert_index_equal(result, exp) | ||||
|  | ||||
|         exp = Index( | ||||
|             [ | ||||
|                 Period("2011-01-01 09:00", freq="h"), | ||||
|                 "x", | ||||
|                 Period("2011-01-01 11:00", freq="h"), | ||||
|             ], | ||||
|             dtype=object, | ||||
|         ) | ||||
|         result = idx.fillna("x") | ||||
|         tm.assert_index_equal(result, exp) | ||||
|  | ||||
|         exp = Index( | ||||
|             [ | ||||
|                 Period("2011-01-01 09:00", freq="h"), | ||||
|                 Period("2011-01-01", freq="D"), | ||||
|                 Period("2011-01-01 11:00", freq="h"), | ||||
|             ], | ||||
|             dtype=object, | ||||
|         ) | ||||
|         result = idx.fillna(Period("2011-01-01", freq="D")) | ||||
|         tm.assert_index_equal(result, exp) | ||||
| @ -0,0 +1,18 @@ | ||||
| import numpy as np | ||||
| import pytest | ||||
|  | ||||
| from pandas import ( | ||||
|     NaT, | ||||
|     PeriodIndex, | ||||
|     period_range, | ||||
| ) | ||||
| import pandas._testing as tm | ||||
|  | ||||
|  | ||||
| class TestInsert: | ||||
|     @pytest.mark.parametrize("na", [np.nan, NaT, None]) | ||||
|     def test_insert(self, na): | ||||
|         # GH#18295 (test missing) | ||||
|         expected = PeriodIndex(["2017Q1", NaT, "2017Q2", "2017Q3", "2017Q4"], freq="Q") | ||||
|         result = period_range("2017Q1", periods=4, freq="Q").insert(1, na) | ||||
|         tm.assert_index_equal(result, expected) | ||||
| @ -0,0 +1,23 @@ | ||||
| import pytest | ||||
|  | ||||
| from pandas import PeriodIndex | ||||
|  | ||||
|  | ||||
| def test_is_full(): | ||||
|     index = PeriodIndex([2005, 2007, 2009], freq="Y") | ||||
|     assert not index.is_full | ||||
|  | ||||
|     index = PeriodIndex([2005, 2006, 2007], freq="Y") | ||||
|     assert index.is_full | ||||
|  | ||||
|     index = PeriodIndex([2005, 2005, 2007], freq="Y") | ||||
|     assert not index.is_full | ||||
|  | ||||
|     index = PeriodIndex([2005, 2005, 2006], freq="Y") | ||||
|     assert index.is_full | ||||
|  | ||||
|     index = PeriodIndex([2006, 2005, 2005], freq="Y") | ||||
|     with pytest.raises(ValueError, match="Index is not monotonic"): | ||||
|         index.is_full | ||||
|  | ||||
|     assert index[:0].is_full | ||||
| @ -0,0 +1,26 @@ | ||||
| import numpy as np | ||||
| import pytest | ||||
|  | ||||
| from pandas import ( | ||||
|     PeriodIndex, | ||||
|     period_range, | ||||
| ) | ||||
| import pandas._testing as tm | ||||
|  | ||||
|  | ||||
| class TestRepeat: | ||||
|     @pytest.mark.parametrize("use_numpy", [True, False]) | ||||
|     @pytest.mark.parametrize( | ||||
|         "index", | ||||
|         [ | ||||
|             period_range("2000-01-01", periods=3, freq="D"), | ||||
|             period_range("2001-01-01", periods=3, freq="2D"), | ||||
|             PeriodIndex(["2001-01", "NaT", "2003-01"], freq="M"), | ||||
|         ], | ||||
|     ) | ||||
|     def test_repeat_freqstr(self, index, use_numpy): | ||||
|         # GH#10183 | ||||
|         expected = PeriodIndex([per for per in index for _ in range(3)]) | ||||
|         result = np.repeat(index, 3) if use_numpy else index.repeat(3) | ||||
|         tm.assert_index_equal(result, expected) | ||||
|         assert result.freqstr == index.freqstr | ||||
| @ -0,0 +1,122 @@ | ||||
| import numpy as np | ||||
| import pytest | ||||
|  | ||||
| from pandas import ( | ||||
|     PeriodIndex, | ||||
|     period_range, | ||||
| ) | ||||
| import pandas._testing as tm | ||||
|  | ||||
|  | ||||
| class TestPeriodIndexShift: | ||||
|     # --------------------------------------------------------------- | ||||
|     # PeriodIndex.shift is used by __add__ and __sub__ | ||||
|  | ||||
|     def test_pi_shift_ndarray(self): | ||||
|         idx = PeriodIndex( | ||||
|             ["2011-01", "2011-02", "NaT", "2011-04"], freq="M", name="idx" | ||||
|         ) | ||||
|         result = idx.shift(np.array([1, 2, 3, 4])) | ||||
|         expected = PeriodIndex( | ||||
|             ["2011-02", "2011-04", "NaT", "2011-08"], freq="M", name="idx" | ||||
|         ) | ||||
|         tm.assert_index_equal(result, expected) | ||||
|  | ||||
|         result = idx.shift(np.array([1, -2, 3, -4])) | ||||
|         expected = PeriodIndex( | ||||
|             ["2011-02", "2010-12", "NaT", "2010-12"], freq="M", name="idx" | ||||
|         ) | ||||
|         tm.assert_index_equal(result, expected) | ||||
|  | ||||
|     def test_shift(self): | ||||
|         pi1 = period_range(freq="Y", start="1/1/2001", end="12/1/2009") | ||||
|         pi2 = period_range(freq="Y", start="1/1/2002", end="12/1/2010") | ||||
|  | ||||
|         tm.assert_index_equal(pi1.shift(0), pi1) | ||||
|  | ||||
|         assert len(pi1) == len(pi2) | ||||
|         tm.assert_index_equal(pi1.shift(1), pi2) | ||||
|  | ||||
|         pi1 = period_range(freq="Y", start="1/1/2001", end="12/1/2009") | ||||
|         pi2 = period_range(freq="Y", start="1/1/2000", end="12/1/2008") | ||||
|         assert len(pi1) == len(pi2) | ||||
|         tm.assert_index_equal(pi1.shift(-1), pi2) | ||||
|  | ||||
|         pi1 = period_range(freq="M", start="1/1/2001", end="12/1/2009") | ||||
|         pi2 = period_range(freq="M", start="2/1/2001", end="1/1/2010") | ||||
|         assert len(pi1) == len(pi2) | ||||
|         tm.assert_index_equal(pi1.shift(1), pi2) | ||||
|  | ||||
|         pi1 = period_range(freq="M", start="1/1/2001", end="12/1/2009") | ||||
|         pi2 = period_range(freq="M", start="12/1/2000", end="11/1/2009") | ||||
|         assert len(pi1) == len(pi2) | ||||
|         tm.assert_index_equal(pi1.shift(-1), pi2) | ||||
|  | ||||
|         pi1 = period_range(freq="D", start="1/1/2001", end="12/1/2009") | ||||
|         pi2 = period_range(freq="D", start="1/2/2001", end="12/2/2009") | ||||
|         assert len(pi1) == len(pi2) | ||||
|         tm.assert_index_equal(pi1.shift(1), pi2) | ||||
|  | ||||
|         pi1 = period_range(freq="D", start="1/1/2001", end="12/1/2009") | ||||
|         pi2 = period_range(freq="D", start="12/31/2000", end="11/30/2009") | ||||
|         assert len(pi1) == len(pi2) | ||||
|         tm.assert_index_equal(pi1.shift(-1), pi2) | ||||
|  | ||||
|     def test_shift_corner_cases(self): | ||||
|         # GH#9903 | ||||
|         idx = PeriodIndex([], name="xxx", freq="h") | ||||
|  | ||||
|         msg = "`freq` argument is not supported for PeriodIndex.shift" | ||||
|         with pytest.raises(TypeError, match=msg): | ||||
|             # period shift doesn't accept freq | ||||
|             idx.shift(1, freq="h") | ||||
|  | ||||
|         tm.assert_index_equal(idx.shift(0), idx) | ||||
|         tm.assert_index_equal(idx.shift(3), idx) | ||||
|  | ||||
|         idx = PeriodIndex( | ||||
|             ["2011-01-01 10:00", "2011-01-01 11:00", "2011-01-01 12:00"], | ||||
|             name="xxx", | ||||
|             freq="h", | ||||
|         ) | ||||
|         tm.assert_index_equal(idx.shift(0), idx) | ||||
|         exp = PeriodIndex( | ||||
|             ["2011-01-01 13:00", "2011-01-01 14:00", "2011-01-01 15:00"], | ||||
|             name="xxx", | ||||
|             freq="h", | ||||
|         ) | ||||
|         tm.assert_index_equal(idx.shift(3), exp) | ||||
|         exp = PeriodIndex( | ||||
|             ["2011-01-01 07:00", "2011-01-01 08:00", "2011-01-01 09:00"], | ||||
|             name="xxx", | ||||
|             freq="h", | ||||
|         ) | ||||
|         tm.assert_index_equal(idx.shift(-3), exp) | ||||
|  | ||||
|     def test_shift_nat(self): | ||||
|         idx = PeriodIndex( | ||||
|             ["2011-01", "2011-02", "NaT", "2011-04"], freq="M", name="idx" | ||||
|         ) | ||||
|         result = idx.shift(1) | ||||
|         expected = PeriodIndex( | ||||
|             ["2011-02", "2011-03", "NaT", "2011-05"], freq="M", name="idx" | ||||
|         ) | ||||
|         tm.assert_index_equal(result, expected) | ||||
|         assert result.name == expected.name | ||||
|  | ||||
|     def test_shift_gh8083(self): | ||||
|         # test shift for PeriodIndex | ||||
|         # GH#8083 | ||||
|         drange = period_range("20130101", periods=5, freq="D") | ||||
|         result = drange.shift(1) | ||||
|         expected = PeriodIndex( | ||||
|             ["2013-01-02", "2013-01-03", "2013-01-04", "2013-01-05", "2013-01-06"], | ||||
|             freq="D", | ||||
|         ) | ||||
|         tm.assert_index_equal(result, expected) | ||||
|  | ||||
|     def test_shift_periods(self): | ||||
|         # GH #22458 : argument 'n' was deprecated in favor of 'periods' | ||||
|         idx = period_range(freq="Y", start="1/1/2001", end="12/1/2009") | ||||
|         tm.assert_index_equal(idx.shift(periods=0), idx) | ||||
|         tm.assert_index_equal(idx.shift(0), idx) | ||||
| @ -0,0 +1,142 @@ | ||||
| from datetime import datetime | ||||
|  | ||||
| import numpy as np | ||||
| import pytest | ||||
|  | ||||
| from pandas import ( | ||||
|     DatetimeIndex, | ||||
|     NaT, | ||||
|     PeriodIndex, | ||||
|     Timedelta, | ||||
|     Timestamp, | ||||
|     date_range, | ||||
|     period_range, | ||||
| ) | ||||
| import pandas._testing as tm | ||||
|  | ||||
|  | ||||
| class TestToTimestamp: | ||||
|     def test_to_timestamp_non_contiguous(self): | ||||
|         # GH#44100 | ||||
|         dti = date_range("2021-10-18", periods=9, freq="D") | ||||
|         pi = dti.to_period() | ||||
|  | ||||
|         result = pi[::2].to_timestamp() | ||||
|         expected = dti[::2] | ||||
|         tm.assert_index_equal(result, expected) | ||||
|  | ||||
|         result = pi._data[::2].to_timestamp() | ||||
|         expected = dti._data[::2] | ||||
|         # TODO: can we get the freq to round-trip? | ||||
|         tm.assert_datetime_array_equal(result, expected, check_freq=False) | ||||
|  | ||||
|         result = pi[::-1].to_timestamp() | ||||
|         expected = dti[::-1] | ||||
|         tm.assert_index_equal(result, expected) | ||||
|  | ||||
|         result = pi._data[::-1].to_timestamp() | ||||
|         expected = dti._data[::-1] | ||||
|         tm.assert_datetime_array_equal(result, expected, check_freq=False) | ||||
|  | ||||
|         result = pi[::2][::-1].to_timestamp() | ||||
|         expected = dti[::2][::-1] | ||||
|         tm.assert_index_equal(result, expected) | ||||
|  | ||||
|         result = pi._data[::2][::-1].to_timestamp() | ||||
|         expected = dti._data[::2][::-1] | ||||
|         tm.assert_datetime_array_equal(result, expected, check_freq=False) | ||||
|  | ||||
|     def test_to_timestamp_freq(self): | ||||
|         idx = period_range("2017", periods=12, freq="Y-DEC") | ||||
|         result = idx.to_timestamp() | ||||
|         expected = date_range("2017", periods=12, freq="YS-JAN") | ||||
|         tm.assert_index_equal(result, expected) | ||||
|  | ||||
|     def test_to_timestamp_pi_nat(self): | ||||
|         # GH#7228 | ||||
|         index = PeriodIndex(["NaT", "2011-01", "2011-02"], freq="M", name="idx") | ||||
|  | ||||
|         result = index.to_timestamp("D") | ||||
|         expected = DatetimeIndex( | ||||
|             [NaT, datetime(2011, 1, 1), datetime(2011, 2, 1)], | ||||
|             dtype="M8[ns]", | ||||
|             name="idx", | ||||
|         ) | ||||
|         tm.assert_index_equal(result, expected) | ||||
|         assert result.name == "idx" | ||||
|  | ||||
|         result2 = result.to_period(freq="M") | ||||
|         tm.assert_index_equal(result2, index) | ||||
|         assert result2.name == "idx" | ||||
|  | ||||
|         result3 = result.to_period(freq="3M") | ||||
|         exp = PeriodIndex(["NaT", "2011-01", "2011-02"], freq="3M", name="idx") | ||||
|         tm.assert_index_equal(result3, exp) | ||||
|         assert result3.freqstr == "3M" | ||||
|  | ||||
|         msg = "Frequency must be positive, because it represents span: -2Y" | ||||
|         with pytest.raises(ValueError, match=msg): | ||||
|             result.to_period(freq="-2Y") | ||||
|  | ||||
|     def test_to_timestamp_preserve_name(self): | ||||
|         index = period_range(freq="Y", start="1/1/2001", end="12/1/2009", name="foo") | ||||
|         assert index.name == "foo" | ||||
|  | ||||
|         conv = index.to_timestamp("D") | ||||
|         assert conv.name == "foo" | ||||
|  | ||||
|     def test_to_timestamp_quarterly_bug(self): | ||||
|         years = np.arange(1960, 2000).repeat(4) | ||||
|         quarters = np.tile(list(range(1, 5)), 40) | ||||
|  | ||||
|         pindex = PeriodIndex.from_fields(year=years, quarter=quarters) | ||||
|  | ||||
|         stamps = pindex.to_timestamp("D", "end") | ||||
|         expected = DatetimeIndex([x.to_timestamp("D", "end") for x in pindex]) | ||||
|         tm.assert_index_equal(stamps, expected) | ||||
|         assert stamps.freq == expected.freq | ||||
|  | ||||
|     def test_to_timestamp_pi_mult(self): | ||||
|         idx = PeriodIndex(["2011-01", "NaT", "2011-02"], freq="2M", name="idx") | ||||
|  | ||||
|         result = idx.to_timestamp() | ||||
|         expected = DatetimeIndex( | ||||
|             ["2011-01-01", "NaT", "2011-02-01"], dtype="M8[ns]", name="idx" | ||||
|         ) | ||||
|         tm.assert_index_equal(result, expected) | ||||
|  | ||||
|         result = idx.to_timestamp(how="E") | ||||
|         expected = DatetimeIndex( | ||||
|             ["2011-02-28", "NaT", "2011-03-31"], dtype="M8[ns]", name="idx" | ||||
|         ) | ||||
|         expected = expected + Timedelta(1, "D") - Timedelta(1, "ns") | ||||
|         tm.assert_index_equal(result, expected) | ||||
|  | ||||
|     def test_to_timestamp_pi_combined(self): | ||||
|         idx = period_range(start="2011", periods=2, freq="1D1h", name="idx") | ||||
|  | ||||
|         result = idx.to_timestamp() | ||||
|         expected = DatetimeIndex( | ||||
|             ["2011-01-01 00:00", "2011-01-02 01:00"], dtype="M8[ns]", name="idx" | ||||
|         ) | ||||
|         tm.assert_index_equal(result, expected) | ||||
|  | ||||
|         result = idx.to_timestamp(how="E") | ||||
|         expected = DatetimeIndex( | ||||
|             ["2011-01-02 00:59:59", "2011-01-03 01:59:59"], name="idx", dtype="M8[ns]" | ||||
|         ) | ||||
|         expected = expected + Timedelta(1, "s") - Timedelta(1, "ns") | ||||
|         tm.assert_index_equal(result, expected) | ||||
|  | ||||
|         result = idx.to_timestamp(how="E", freq="h") | ||||
|         expected = DatetimeIndex( | ||||
|             ["2011-01-02 00:00", "2011-01-03 01:00"], dtype="M8[ns]", name="idx" | ||||
|         ) | ||||
|         expected = expected + Timedelta(1, "h") - Timedelta(1, "ns") | ||||
|         tm.assert_index_equal(result, expected) | ||||
|  | ||||
|     def test_to_timestamp_1703(self): | ||||
|         index = period_range("1/1/2012", periods=4, freq="D") | ||||
|  | ||||
|         result = index.to_timestamp() | ||||
|         assert result[0] == Timestamp("1/1/2012") | ||||
| @ -0,0 +1,691 @@ | ||||
| import numpy as np | ||||
| import pytest | ||||
|  | ||||
| from pandas._libs.tslibs.period import IncompatibleFrequency | ||||
|  | ||||
| from pandas.core.dtypes.dtypes import PeriodDtype | ||||
|  | ||||
| from pandas import ( | ||||
|     Index, | ||||
|     NaT, | ||||
|     Period, | ||||
|     PeriodIndex, | ||||
|     Series, | ||||
|     date_range, | ||||
|     offsets, | ||||
|     period_range, | ||||
| ) | ||||
| import pandas._testing as tm | ||||
| from pandas.core.arrays import PeriodArray | ||||
|  | ||||
|  | ||||
| class TestPeriodIndexDisallowedFreqs: | ||||
|     @pytest.mark.parametrize( | ||||
|         "freq,freq_depr", | ||||
|         [ | ||||
|             ("2M", "2ME"), | ||||
|             ("2Q-MAR", "2QE-MAR"), | ||||
|             ("2Y-FEB", "2YE-FEB"), | ||||
|             ("2M", "2me"), | ||||
|             ("2Q-MAR", "2qe-MAR"), | ||||
|             ("2Y-FEB", "2yE-feb"), | ||||
|         ], | ||||
|     ) | ||||
|     def test_period_index_offsets_frequency_error_message(self, freq, freq_depr): | ||||
|         # GH#52064 | ||||
|         msg = f"for Period, please use '{freq[1:]}' instead of '{freq_depr[1:]}'" | ||||
|  | ||||
|         with pytest.raises(ValueError, match=msg): | ||||
|             PeriodIndex(["2020-01-01", "2020-01-02"], freq=freq_depr) | ||||
|  | ||||
|         with pytest.raises(ValueError, match=msg): | ||||
|             period_range(start="2020-01-01", end="2020-01-02", freq=freq_depr) | ||||
|  | ||||
|     @pytest.mark.parametrize("freq_depr", ["2SME", "2sme", "2CBME", "2BYE", "2Bye"]) | ||||
|     def test_period_index_frequency_invalid_freq(self, freq_depr): | ||||
|         # GH#9586 | ||||
|         msg = f"Invalid frequency: {freq_depr[1:]}" | ||||
|  | ||||
|         with pytest.raises(ValueError, match=msg): | ||||
|             period_range("2020-01", "2020-05", freq=freq_depr) | ||||
|         with pytest.raises(ValueError, match=msg): | ||||
|             PeriodIndex(["2020-01", "2020-05"], freq=freq_depr) | ||||
|  | ||||
|     @pytest.mark.parametrize("freq", ["2BQE-SEP", "2BYE-MAR", "2BME"]) | ||||
|     def test_period_index_from_datetime_index_invalid_freq(self, freq): | ||||
|         # GH#56899 | ||||
|         msg = f"Invalid frequency: {freq[1:]}" | ||||
|  | ||||
|         rng = date_range("01-Jan-2012", periods=8, freq=freq) | ||||
|         with pytest.raises(ValueError, match=msg): | ||||
|             rng.to_period() | ||||
|  | ||||
|  | ||||
| class TestPeriodIndex: | ||||
|     def test_from_ordinals(self): | ||||
|         Period(ordinal=-1000, freq="Y") | ||||
|         Period(ordinal=0, freq="Y") | ||||
|  | ||||
|         msg = "The 'ordinal' keyword in PeriodIndex is deprecated" | ||||
|         with tm.assert_produces_warning(FutureWarning, match=msg): | ||||
|             idx1 = PeriodIndex(ordinal=[-1, 0, 1], freq="Y") | ||||
|         with tm.assert_produces_warning(FutureWarning, match=msg): | ||||
|             idx2 = PeriodIndex(ordinal=np.array([-1, 0, 1]), freq="Y") | ||||
|         tm.assert_index_equal(idx1, idx2) | ||||
|  | ||||
|         alt1 = PeriodIndex.from_ordinals([-1, 0, 1], freq="Y") | ||||
|         tm.assert_index_equal(alt1, idx1) | ||||
|  | ||||
|         alt2 = PeriodIndex.from_ordinals(np.array([-1, 0, 1]), freq="Y") | ||||
|         tm.assert_index_equal(alt2, idx2) | ||||
|  | ||||
|     def test_keyword_mismatch(self): | ||||
|         # GH#55961 we should get exactly one of data/ordinals/**fields | ||||
|         per = Period("2016-01-01", "D") | ||||
|         depr_msg1 = "The 'ordinal' keyword in PeriodIndex is deprecated" | ||||
|         depr_msg2 = "Constructing PeriodIndex from fields is deprecated" | ||||
|  | ||||
|         err_msg1 = "Cannot pass both data and ordinal" | ||||
|         with pytest.raises(ValueError, match=err_msg1): | ||||
|             with tm.assert_produces_warning(FutureWarning, match=depr_msg1): | ||||
|                 PeriodIndex(data=[per], ordinal=[per.ordinal], freq=per.freq) | ||||
|  | ||||
|         err_msg2 = "Cannot pass both data and fields" | ||||
|         with pytest.raises(ValueError, match=err_msg2): | ||||
|             with tm.assert_produces_warning(FutureWarning, match=depr_msg2): | ||||
|                 PeriodIndex(data=[per], year=[per.year], freq=per.freq) | ||||
|  | ||||
|         err_msg3 = "Cannot pass both ordinal and fields" | ||||
|         with pytest.raises(ValueError, match=err_msg3): | ||||
|             with tm.assert_produces_warning(FutureWarning, match=depr_msg2): | ||||
|                 PeriodIndex(ordinal=[per.ordinal], year=[per.year], freq=per.freq) | ||||
|  | ||||
|     def test_construction_base_constructor(self): | ||||
|         # GH 13664 | ||||
|         arr = [Period("2011-01", freq="M"), NaT, Period("2011-03", freq="M")] | ||||
|         tm.assert_index_equal(Index(arr), PeriodIndex(arr)) | ||||
|         tm.assert_index_equal(Index(np.array(arr)), PeriodIndex(np.array(arr))) | ||||
|  | ||||
|         arr = [np.nan, NaT, Period("2011-03", freq="M")] | ||||
|         tm.assert_index_equal(Index(arr), PeriodIndex(arr)) | ||||
|         tm.assert_index_equal(Index(np.array(arr)), PeriodIndex(np.array(arr))) | ||||
|  | ||||
|         arr = [Period("2011-01", freq="M"), NaT, Period("2011-03", freq="D")] | ||||
|         tm.assert_index_equal(Index(arr), Index(arr, dtype=object)) | ||||
|  | ||||
|         tm.assert_index_equal(Index(np.array(arr)), Index(np.array(arr), dtype=object)) | ||||
|  | ||||
|     def test_base_constructor_with_period_dtype(self): | ||||
|         dtype = PeriodDtype("D") | ||||
|         values = ["2011-01-01", "2012-03-04", "2014-05-01"] | ||||
|         result = Index(values, dtype=dtype) | ||||
|  | ||||
|         expected = PeriodIndex(values, dtype=dtype) | ||||
|         tm.assert_index_equal(result, expected) | ||||
|  | ||||
|     @pytest.mark.parametrize( | ||||
|         "values_constructor", [list, np.array, PeriodIndex, PeriodArray._from_sequence] | ||||
|     ) | ||||
|     def test_index_object_dtype(self, values_constructor): | ||||
|         # Index(periods, dtype=object) is an Index (not an PeriodIndex) | ||||
|         periods = [ | ||||
|             Period("2011-01", freq="M"), | ||||
|             NaT, | ||||
|             Period("2011-03", freq="M"), | ||||
|         ] | ||||
|         values = values_constructor(periods) | ||||
|         result = Index(values, dtype=object) | ||||
|  | ||||
|         assert type(result) is Index | ||||
|         tm.assert_numpy_array_equal(result.values, np.array(values)) | ||||
|  | ||||
|     def test_constructor_use_start_freq(self): | ||||
|         # GH #1118 | ||||
|         msg1 = "Period with BDay freq is deprecated" | ||||
|         with tm.assert_produces_warning(FutureWarning, match=msg1): | ||||
|             p = Period("4/2/2012", freq="B") | ||||
|         msg2 = r"PeriodDtype\[B\] is deprecated" | ||||
|         with tm.assert_produces_warning(FutureWarning, match=msg2): | ||||
|             expected = period_range(start="4/2/2012", periods=10, freq="B") | ||||
|  | ||||
|         with tm.assert_produces_warning(FutureWarning, match=msg2): | ||||
|             index = period_range(start=p, periods=10) | ||||
|         tm.assert_index_equal(index, expected) | ||||
|  | ||||
|     def test_constructor_field_arrays(self): | ||||
|         # GH #1264 | ||||
|  | ||||
|         years = np.arange(1990, 2010).repeat(4)[2:-2] | ||||
|         quarters = np.tile(np.arange(1, 5), 20)[2:-2] | ||||
|  | ||||
|         depr_msg = "Constructing PeriodIndex from fields is deprecated" | ||||
|         with tm.assert_produces_warning(FutureWarning, match=depr_msg): | ||||
|             index = PeriodIndex(year=years, quarter=quarters, freq="Q-DEC") | ||||
|         expected = period_range("1990Q3", "2009Q2", freq="Q-DEC") | ||||
|         tm.assert_index_equal(index, expected) | ||||
|  | ||||
|         with tm.assert_produces_warning(FutureWarning, match=depr_msg): | ||||
|             index2 = PeriodIndex(year=years, quarter=quarters, freq="2Q-DEC") | ||||
|         tm.assert_numpy_array_equal(index.asi8, index2.asi8) | ||||
|  | ||||
|         with tm.assert_produces_warning(FutureWarning, match=depr_msg): | ||||
|             index = PeriodIndex(year=years, quarter=quarters) | ||||
|         tm.assert_index_equal(index, expected) | ||||
|  | ||||
|         years = [2007, 2007, 2007] | ||||
|         months = [1, 2] | ||||
|  | ||||
|         msg = "Mismatched Period array lengths" | ||||
|         with pytest.raises(ValueError, match=msg): | ||||
|             with tm.assert_produces_warning(FutureWarning, match=depr_msg): | ||||
|                 PeriodIndex(year=years, month=months, freq="M") | ||||
|         with pytest.raises(ValueError, match=msg): | ||||
|             with tm.assert_produces_warning(FutureWarning, match=depr_msg): | ||||
|                 PeriodIndex(year=years, month=months, freq="2M") | ||||
|  | ||||
|         years = [2007, 2007, 2007] | ||||
|         months = [1, 2, 3] | ||||
|         with tm.assert_produces_warning(FutureWarning, match=depr_msg): | ||||
|             idx = PeriodIndex(year=years, month=months, freq="M") | ||||
|         exp = period_range("2007-01", periods=3, freq="M") | ||||
|         tm.assert_index_equal(idx, exp) | ||||
|  | ||||
|     def test_constructor_nano(self): | ||||
|         idx = period_range( | ||||
|             start=Period(ordinal=1, freq="ns"), | ||||
|             end=Period(ordinal=4, freq="ns"), | ||||
|             freq="ns", | ||||
|         ) | ||||
|         exp = PeriodIndex( | ||||
|             [ | ||||
|                 Period(ordinal=1, freq="ns"), | ||||
|                 Period(ordinal=2, freq="ns"), | ||||
|                 Period(ordinal=3, freq="ns"), | ||||
|                 Period(ordinal=4, freq="ns"), | ||||
|             ], | ||||
|             freq="ns", | ||||
|         ) | ||||
|         tm.assert_index_equal(idx, exp) | ||||
|  | ||||
|     def test_constructor_arrays_negative_year(self): | ||||
|         years = np.arange(1960, 2000, dtype=np.int64).repeat(4) | ||||
|         quarters = np.tile(np.array([1, 2, 3, 4], dtype=np.int64), 40) | ||||
|  | ||||
|         msg = "Constructing PeriodIndex from fields is deprecated" | ||||
|         with tm.assert_produces_warning(FutureWarning, match=msg): | ||||
|             pindex = PeriodIndex(year=years, quarter=quarters) | ||||
|  | ||||
|         tm.assert_index_equal(pindex.year, Index(years)) | ||||
|         tm.assert_index_equal(pindex.quarter, Index(quarters)) | ||||
|  | ||||
|         alt = PeriodIndex.from_fields(year=years, quarter=quarters) | ||||
|         tm.assert_index_equal(alt, pindex) | ||||
|  | ||||
|     def test_constructor_invalid_quarters(self): | ||||
|         depr_msg = "Constructing PeriodIndex from fields is deprecated" | ||||
|         msg = "Quarter must be 1 <= q <= 4" | ||||
|         with pytest.raises(ValueError, match=msg): | ||||
|             with tm.assert_produces_warning(FutureWarning, match=depr_msg): | ||||
|                 PeriodIndex( | ||||
|                     year=range(2000, 2004), quarter=list(range(4)), freq="Q-DEC" | ||||
|                 ) | ||||
|  | ||||
|     def test_period_range_fractional_period(self): | ||||
|         msg = "Non-integer 'periods' in pd.date_range, pd.timedelta_range" | ||||
|         with tm.assert_produces_warning(FutureWarning, match=msg): | ||||
|             result = period_range("2007-01", periods=10.5, freq="M") | ||||
|         exp = period_range("2007-01", periods=10, freq="M") | ||||
|         tm.assert_index_equal(result, exp) | ||||
|  | ||||
|     def test_constructor_with_without_freq(self): | ||||
|         # GH53687 | ||||
|         start = Period("2002-01-01 00:00", freq="30min") | ||||
|         exp = period_range(start=start, periods=5, freq=start.freq) | ||||
|         result = period_range(start=start, periods=5) | ||||
|         tm.assert_index_equal(exp, result) | ||||
|  | ||||
|     def test_constructor_fromarraylike(self): | ||||
|         idx = period_range("2007-01", periods=20, freq="M") | ||||
|  | ||||
|         # values is an array of Period, thus can retrieve freq | ||||
|         tm.assert_index_equal(PeriodIndex(idx.values), idx) | ||||
|         tm.assert_index_equal(PeriodIndex(list(idx.values)), idx) | ||||
|  | ||||
|         msg = "freq not specified and cannot be inferred" | ||||
|         with pytest.raises(ValueError, match=msg): | ||||
|             PeriodIndex(idx.asi8) | ||||
|         with pytest.raises(ValueError, match=msg): | ||||
|             PeriodIndex(list(idx.asi8)) | ||||
|  | ||||
|         msg = "'Period' object is not iterable" | ||||
|         with pytest.raises(TypeError, match=msg): | ||||
|             PeriodIndex(data=Period("2007", freq="Y")) | ||||
|  | ||||
|         result = PeriodIndex(iter(idx)) | ||||
|         tm.assert_index_equal(result, idx) | ||||
|  | ||||
|         result = PeriodIndex(idx) | ||||
|         tm.assert_index_equal(result, idx) | ||||
|  | ||||
|         result = PeriodIndex(idx, freq="M") | ||||
|         tm.assert_index_equal(result, idx) | ||||
|  | ||||
|         result = PeriodIndex(idx, freq=offsets.MonthEnd()) | ||||
|         tm.assert_index_equal(result, idx) | ||||
|         assert result.freq == "ME" | ||||
|  | ||||
|         result = PeriodIndex(idx, freq="2M") | ||||
|         tm.assert_index_equal(result, idx.asfreq("2M")) | ||||
|         assert result.freq == "2ME" | ||||
|  | ||||
|         result = PeriodIndex(idx, freq=offsets.MonthEnd(2)) | ||||
|         tm.assert_index_equal(result, idx.asfreq("2M")) | ||||
|         assert result.freq == "2ME" | ||||
|  | ||||
|         result = PeriodIndex(idx, freq="D") | ||||
|         exp = idx.asfreq("D", "e") | ||||
|         tm.assert_index_equal(result, exp) | ||||
|  | ||||
|     def test_constructor_datetime64arr(self): | ||||
|         vals = np.arange(100000, 100000 + 10000, 100, dtype=np.int64) | ||||
|         vals = vals.view(np.dtype("M8[us]")) | ||||
|  | ||||
|         pi = PeriodIndex(vals, freq="D") | ||||
|  | ||||
|         expected = PeriodIndex(vals.astype("M8[ns]"), freq="D") | ||||
|         tm.assert_index_equal(pi, expected) | ||||
|  | ||||
|     @pytest.mark.parametrize("box", [None, "series", "index"]) | ||||
|     def test_constructor_datetime64arr_ok(self, box): | ||||
|         # https://github.com/pandas-dev/pandas/issues/23438 | ||||
|         data = date_range("2017", periods=4, freq="ME") | ||||
|         if box is None: | ||||
|             data = data._values | ||||
|         elif box == "series": | ||||
|             data = Series(data) | ||||
|  | ||||
|         result = PeriodIndex(data, freq="D") | ||||
|         expected = PeriodIndex( | ||||
|             ["2017-01-31", "2017-02-28", "2017-03-31", "2017-04-30"], freq="D" | ||||
|         ) | ||||
|         tm.assert_index_equal(result, expected) | ||||
|  | ||||
|     def test_constructor_dtype(self): | ||||
|         # passing a dtype with a tz should localize | ||||
|         idx = PeriodIndex(["2013-01", "2013-03"], dtype="period[M]") | ||||
|         exp = PeriodIndex(["2013-01", "2013-03"], freq="M") | ||||
|         tm.assert_index_equal(idx, exp) | ||||
|         assert idx.dtype == "period[M]" | ||||
|  | ||||
|         idx = PeriodIndex(["2013-01-05", "2013-03-05"], dtype="period[3D]") | ||||
|         exp = PeriodIndex(["2013-01-05", "2013-03-05"], freq="3D") | ||||
|         tm.assert_index_equal(idx, exp) | ||||
|         assert idx.dtype == "period[3D]" | ||||
|  | ||||
|         # if we already have a freq and its not the same, then asfreq | ||||
|         # (not changed) | ||||
|         idx = PeriodIndex(["2013-01-01", "2013-01-02"], freq="D") | ||||
|  | ||||
|         res = PeriodIndex(idx, dtype="period[M]") | ||||
|         exp = PeriodIndex(["2013-01", "2013-01"], freq="M") | ||||
|         tm.assert_index_equal(res, exp) | ||||
|         assert res.dtype == "period[M]" | ||||
|  | ||||
|         res = PeriodIndex(idx, freq="M") | ||||
|         tm.assert_index_equal(res, exp) | ||||
|         assert res.dtype == "period[M]" | ||||
|  | ||||
|         msg = "specified freq and dtype are different" | ||||
|         with pytest.raises(IncompatibleFrequency, match=msg): | ||||
|             PeriodIndex(["2011-01"], freq="M", dtype="period[D]") | ||||
|  | ||||
|     def test_constructor_empty(self): | ||||
|         idx = PeriodIndex([], freq="M") | ||||
|         assert isinstance(idx, PeriodIndex) | ||||
|         assert len(idx) == 0 | ||||
|         assert idx.freq == "ME" | ||||
|  | ||||
|         with pytest.raises(ValueError, match="freq not specified"): | ||||
|             PeriodIndex([]) | ||||
|  | ||||
|     def test_constructor_pi_nat(self): | ||||
|         idx = PeriodIndex( | ||||
|             [Period("2011-01", freq="M"), NaT, Period("2011-01", freq="M")] | ||||
|         ) | ||||
|         exp = PeriodIndex(["2011-01", "NaT", "2011-01"], freq="M") | ||||
|         tm.assert_index_equal(idx, exp) | ||||
|  | ||||
|         idx = PeriodIndex( | ||||
|             np.array([Period("2011-01", freq="M"), NaT, Period("2011-01", freq="M")]) | ||||
|         ) | ||||
|         tm.assert_index_equal(idx, exp) | ||||
|  | ||||
|         idx = PeriodIndex( | ||||
|             [NaT, NaT, Period("2011-01", freq="M"), Period("2011-01", freq="M")] | ||||
|         ) | ||||
|         exp = PeriodIndex(["NaT", "NaT", "2011-01", "2011-01"], freq="M") | ||||
|         tm.assert_index_equal(idx, exp) | ||||
|  | ||||
|         idx = PeriodIndex( | ||||
|             np.array( | ||||
|                 [NaT, NaT, Period("2011-01", freq="M"), Period("2011-01", freq="M")] | ||||
|             ) | ||||
|         ) | ||||
|         tm.assert_index_equal(idx, exp) | ||||
|  | ||||
|         idx = PeriodIndex([NaT, NaT, "2011-01", "2011-01"], freq="M") | ||||
|         tm.assert_index_equal(idx, exp) | ||||
|  | ||||
|         with pytest.raises(ValueError, match="freq not specified"): | ||||
|             PeriodIndex([NaT, NaT]) | ||||
|  | ||||
|         with pytest.raises(ValueError, match="freq not specified"): | ||||
|             PeriodIndex(np.array([NaT, NaT])) | ||||
|  | ||||
|         with pytest.raises(ValueError, match="freq not specified"): | ||||
|             PeriodIndex(["NaT", "NaT"]) | ||||
|  | ||||
|         with pytest.raises(ValueError, match="freq not specified"): | ||||
|             PeriodIndex(np.array(["NaT", "NaT"])) | ||||
|  | ||||
|     def test_constructor_incompat_freq(self): | ||||
|         msg = "Input has different freq=D from PeriodIndex\\(freq=M\\)" | ||||
|  | ||||
|         with pytest.raises(IncompatibleFrequency, match=msg): | ||||
|             PeriodIndex([Period("2011-01", freq="M"), NaT, Period("2011-01", freq="D")]) | ||||
|  | ||||
|         with pytest.raises(IncompatibleFrequency, match=msg): | ||||
|             PeriodIndex( | ||||
|                 np.array( | ||||
|                     [Period("2011-01", freq="M"), NaT, Period("2011-01", freq="D")] | ||||
|                 ) | ||||
|             ) | ||||
|  | ||||
|         # first element is NaT | ||||
|         with pytest.raises(IncompatibleFrequency, match=msg): | ||||
|             PeriodIndex([NaT, Period("2011-01", freq="M"), Period("2011-01", freq="D")]) | ||||
|  | ||||
|         with pytest.raises(IncompatibleFrequency, match=msg): | ||||
|             PeriodIndex( | ||||
|                 np.array( | ||||
|                     [NaT, Period("2011-01", freq="M"), Period("2011-01", freq="D")] | ||||
|                 ) | ||||
|             ) | ||||
|  | ||||
|     def test_constructor_mixed(self): | ||||
|         idx = PeriodIndex(["2011-01", NaT, Period("2011-01", freq="M")]) | ||||
|         exp = PeriodIndex(["2011-01", "NaT", "2011-01"], freq="M") | ||||
|         tm.assert_index_equal(idx, exp) | ||||
|  | ||||
|         idx = PeriodIndex(["NaT", NaT, Period("2011-01", freq="M")]) | ||||
|         exp = PeriodIndex(["NaT", "NaT", "2011-01"], freq="M") | ||||
|         tm.assert_index_equal(idx, exp) | ||||
|  | ||||
|         idx = PeriodIndex([Period("2011-01-01", freq="D"), NaT, "2012-01-01"]) | ||||
|         exp = PeriodIndex(["2011-01-01", "NaT", "2012-01-01"], freq="D") | ||||
|         tm.assert_index_equal(idx, exp) | ||||
|  | ||||
|     @pytest.mark.parametrize("floats", [[1.1, 2.1], np.array([1.1, 2.1])]) | ||||
|     def test_constructor_floats(self, floats): | ||||
|         msg = "PeriodIndex does not allow floating point in construction" | ||||
|         with pytest.raises(TypeError, match=msg): | ||||
|             PeriodIndex(floats) | ||||
|  | ||||
|     def test_constructor_year_and_quarter(self): | ||||
|         year = Series([2001, 2002, 2003]) | ||||
|         quarter = year - 2000 | ||||
|         msg = "Constructing PeriodIndex from fields is deprecated" | ||||
|         with tm.assert_produces_warning(FutureWarning, match=msg): | ||||
|             idx = PeriodIndex(year=year, quarter=quarter) | ||||
|         strs = [f"{t[0]:d}Q{t[1]:d}" for t in zip(quarter, year)] | ||||
|         lops = list(map(Period, strs)) | ||||
|         p = PeriodIndex(lops) | ||||
|         tm.assert_index_equal(p, idx) | ||||
|  | ||||
|     def test_constructor_freq_mult(self): | ||||
|         # GH #7811 | ||||
|         pidx = period_range(start="2014-01", freq="2M", periods=4) | ||||
|         expected = PeriodIndex(["2014-01", "2014-03", "2014-05", "2014-07"], freq="2M") | ||||
|         tm.assert_index_equal(pidx, expected) | ||||
|  | ||||
|         pidx = period_range(start="2014-01-02", end="2014-01-15", freq="3D") | ||||
|         expected = PeriodIndex( | ||||
|             ["2014-01-02", "2014-01-05", "2014-01-08", "2014-01-11", "2014-01-14"], | ||||
|             freq="3D", | ||||
|         ) | ||||
|         tm.assert_index_equal(pidx, expected) | ||||
|  | ||||
|         pidx = period_range(end="2014-01-01 17:00", freq="4h", periods=3) | ||||
|         expected = PeriodIndex( | ||||
|             ["2014-01-01 09:00", "2014-01-01 13:00", "2014-01-01 17:00"], freq="4h" | ||||
|         ) | ||||
|         tm.assert_index_equal(pidx, expected) | ||||
|  | ||||
|         msg = "Frequency must be positive, because it represents span: -1M" | ||||
|         with pytest.raises(ValueError, match=msg): | ||||
|             PeriodIndex(["2011-01"], freq="-1M") | ||||
|  | ||||
|         msg = "Frequency must be positive, because it represents span: 0M" | ||||
|         with pytest.raises(ValueError, match=msg): | ||||
|             PeriodIndex(["2011-01"], freq="0M") | ||||
|  | ||||
|         msg = "Frequency must be positive, because it represents span: 0M" | ||||
|         with pytest.raises(ValueError, match=msg): | ||||
|             period_range("2011-01", periods=3, freq="0M") | ||||
|  | ||||
|     @pytest.mark.parametrize( | ||||
|         "freq_offset, freq_period", | ||||
|         [ | ||||
|             ("YE", "Y"), | ||||
|             ("ME", "M"), | ||||
|             ("D", "D"), | ||||
|             ("min", "min"), | ||||
|             ("s", "s"), | ||||
|         ], | ||||
|     ) | ||||
|     @pytest.mark.parametrize("mult", [1, 2, 3, 4, 5]) | ||||
|     def test_constructor_freq_mult_dti_compat(self, mult, freq_offset, freq_period): | ||||
|         freqstr_offset = str(mult) + freq_offset | ||||
|         freqstr_period = str(mult) + freq_period | ||||
|         pidx = period_range(start="2014-04-01", freq=freqstr_period, periods=10) | ||||
|         expected = date_range( | ||||
|             start="2014-04-01", freq=freqstr_offset, periods=10 | ||||
|         ).to_period(freqstr_period) | ||||
|         tm.assert_index_equal(pidx, expected) | ||||
|  | ||||
|     @pytest.mark.parametrize("mult", [1, 2, 3, 4, 5]) | ||||
|     def test_constructor_freq_mult_dti_compat_month(self, mult): | ||||
|         pidx = period_range(start="2014-04-01", freq=f"{mult}M", periods=10) | ||||
|         expected = date_range( | ||||
|             start="2014-04-01", freq=f"{mult}ME", periods=10 | ||||
|         ).to_period(f"{mult}M") | ||||
|         tm.assert_index_equal(pidx, expected) | ||||
|  | ||||
|     def test_constructor_freq_combined(self): | ||||
|         for freq in ["1D1h", "1h1D"]: | ||||
|             pidx = PeriodIndex(["2016-01-01", "2016-01-02"], freq=freq) | ||||
|             expected = PeriodIndex(["2016-01-01 00:00", "2016-01-02 00:00"], freq="25h") | ||||
|         for freq in ["1D1h", "1h1D"]: | ||||
|             pidx = period_range(start="2016-01-01", periods=2, freq=freq) | ||||
|             expected = PeriodIndex(["2016-01-01 00:00", "2016-01-02 01:00"], freq="25h") | ||||
|             tm.assert_index_equal(pidx, expected) | ||||
|  | ||||
|     def test_period_range_length(self): | ||||
|         pi = period_range(freq="Y", start="1/1/2001", end="12/1/2009") | ||||
|         assert len(pi) == 9 | ||||
|  | ||||
|         pi = period_range(freq="Q", start="1/1/2001", end="12/1/2009") | ||||
|         assert len(pi) == 4 * 9 | ||||
|  | ||||
|         pi = period_range(freq="M", start="1/1/2001", end="12/1/2009") | ||||
|         assert len(pi) == 12 * 9 | ||||
|  | ||||
|         pi = period_range(freq="D", start="1/1/2001", end="12/31/2009") | ||||
|         assert len(pi) == 365 * 9 + 2 | ||||
|  | ||||
|         msg = "Period with BDay freq is deprecated" | ||||
|         with tm.assert_produces_warning(FutureWarning, match=msg): | ||||
|             pi = period_range(freq="B", start="1/1/2001", end="12/31/2009") | ||||
|         assert len(pi) == 261 * 9 | ||||
|  | ||||
|         pi = period_range(freq="h", start="1/1/2001", end="12/31/2001 23:00") | ||||
|         assert len(pi) == 365 * 24 | ||||
|  | ||||
|         pi = period_range(freq="Min", start="1/1/2001", end="1/1/2001 23:59") | ||||
|         assert len(pi) == 24 * 60 | ||||
|  | ||||
|         pi = period_range(freq="s", start="1/1/2001", end="1/1/2001 23:59:59") | ||||
|         assert len(pi) == 24 * 60 * 60 | ||||
|  | ||||
|         with tm.assert_produces_warning(FutureWarning, match=msg): | ||||
|             start = Period("02-Apr-2005", "B") | ||||
|             i1 = period_range(start=start, periods=20) | ||||
|         assert len(i1) == 20 | ||||
|         assert i1.freq == start.freq | ||||
|         assert i1[0] == start | ||||
|  | ||||
|         end_intv = Period("2006-12-31", "W") | ||||
|         i1 = period_range(end=end_intv, periods=10) | ||||
|         assert len(i1) == 10 | ||||
|         assert i1.freq == end_intv.freq | ||||
|         assert i1[-1] == end_intv | ||||
|  | ||||
|         msg = "'w' is deprecated and will be removed in a future version." | ||||
|         with tm.assert_produces_warning(FutureWarning, match=msg): | ||||
|             end_intv = Period("2006-12-31", "1w") | ||||
|         i2 = period_range(end=end_intv, periods=10) | ||||
|         assert len(i1) == len(i2) | ||||
|         assert (i1 == i2).all() | ||||
|         assert i1.freq == i2.freq | ||||
|  | ||||
|     def test_infer_freq_from_first_element(self): | ||||
|         msg = "Period with BDay freq is deprecated" | ||||
|         with tm.assert_produces_warning(FutureWarning, match=msg): | ||||
|             start = Period("02-Apr-2005", "B") | ||||
|             end_intv = Period("2005-05-01", "B") | ||||
|             period_range(start=start, end=end_intv) | ||||
|  | ||||
|             # infer freq from first element | ||||
|             i2 = PeriodIndex([end_intv, Period("2005-05-05", "B")]) | ||||
|         assert len(i2) == 2 | ||||
|         assert i2[0] == end_intv | ||||
|  | ||||
|         with tm.assert_produces_warning(FutureWarning, match=msg): | ||||
|             i2 = PeriodIndex(np.array([end_intv, Period("2005-05-05", "B")])) | ||||
|         assert len(i2) == 2 | ||||
|         assert i2[0] == end_intv | ||||
|  | ||||
|     def test_mixed_freq_raises(self): | ||||
|         # Mixed freq should fail | ||||
|         msg = "Period with BDay freq is deprecated" | ||||
|         with tm.assert_produces_warning(FutureWarning, match=msg): | ||||
|             end_intv = Period("2005-05-01", "B") | ||||
|  | ||||
|         msg = "'w' is deprecated and will be removed in a future version." | ||||
|         with tm.assert_produces_warning(FutureWarning, match=msg): | ||||
|             vals = [end_intv, Period("2006-12-31", "w")] | ||||
|         msg = r"Input has different freq=W-SUN from PeriodIndex\(freq=B\)" | ||||
|         depr_msg = r"PeriodDtype\[B\] is deprecated" | ||||
|         with pytest.raises(IncompatibleFrequency, match=msg): | ||||
|             with tm.assert_produces_warning(FutureWarning, match=depr_msg): | ||||
|                 PeriodIndex(vals) | ||||
|         vals = np.array(vals) | ||||
|         with pytest.raises(IncompatibleFrequency, match=msg): | ||||
|             with tm.assert_produces_warning(FutureWarning, match=depr_msg): | ||||
|                 PeriodIndex(vals) | ||||
|  | ||||
|     @pytest.mark.parametrize( | ||||
|         "freq", ["M", "Q", "Y", "D", "B", "min", "s", "ms", "us", "ns", "h"] | ||||
|     ) | ||||
|     @pytest.mark.filterwarnings( | ||||
|         r"ignore:Period with BDay freq is deprecated:FutureWarning" | ||||
|     ) | ||||
|     @pytest.mark.filterwarnings(r"ignore:PeriodDtype\[B\] is deprecated:FutureWarning") | ||||
|     def test_recreate_from_data(self, freq): | ||||
|         org = period_range(start="2001/04/01", freq=freq, periods=1) | ||||
|         idx = PeriodIndex(org.values, freq=freq) | ||||
|         tm.assert_index_equal(idx, org) | ||||
|  | ||||
|     def test_map_with_string_constructor(self): | ||||
|         raw = [2005, 2007, 2009] | ||||
|         index = PeriodIndex(raw, freq="Y") | ||||
|  | ||||
|         expected = Index([str(num) for num in raw]) | ||||
|         res = index.map(str) | ||||
|  | ||||
|         # should return an Index | ||||
|         assert isinstance(res, Index) | ||||
|  | ||||
|         # preserve element types | ||||
|         assert all(isinstance(resi, str) for resi in res) | ||||
|  | ||||
|         # lastly, values should compare equal | ||||
|         tm.assert_index_equal(res, expected) | ||||
|  | ||||
|  | ||||
| class TestSimpleNew: | ||||
|     def test_constructor_simple_new(self): | ||||
|         idx = period_range("2007-01", name="p", periods=2, freq="M") | ||||
|  | ||||
|         with pytest.raises(AssertionError, match="<class .*PeriodIndex'>"): | ||||
|             idx._simple_new(idx, name="p") | ||||
|  | ||||
|         result = idx._simple_new(idx._data, name="p") | ||||
|         tm.assert_index_equal(result, idx) | ||||
|  | ||||
|         msg = "Should be numpy array of type i8" | ||||
|         with pytest.raises(AssertionError, match=msg): | ||||
|             # Need ndarray, not int64 Index | ||||
|             type(idx._data)._simple_new(Index(idx.asi8), dtype=idx.dtype) | ||||
|  | ||||
|         arr = type(idx._data)._simple_new(idx.asi8, dtype=idx.dtype) | ||||
|         result = idx._simple_new(arr, name="p") | ||||
|         tm.assert_index_equal(result, idx) | ||||
|  | ||||
|     def test_constructor_simple_new_empty(self): | ||||
|         # GH13079 | ||||
|         idx = PeriodIndex([], freq="M", name="p") | ||||
|         with pytest.raises(AssertionError, match="<class .*PeriodIndex'>"): | ||||
|             idx._simple_new(idx, name="p") | ||||
|  | ||||
|         result = idx._simple_new(idx._data, name="p") | ||||
|         tm.assert_index_equal(result, idx) | ||||
|  | ||||
|     @pytest.mark.parametrize("floats", [[1.1, 2.1], np.array([1.1, 2.1])]) | ||||
|     def test_period_index_simple_new_disallows_floats(self, floats): | ||||
|         with pytest.raises(AssertionError, match="<class "): | ||||
|             PeriodIndex._simple_new(floats) | ||||
|  | ||||
|  | ||||
| class TestShallowCopy: | ||||
|     def test_shallow_copy_empty(self): | ||||
|         # GH#13067 | ||||
|         idx = PeriodIndex([], freq="M") | ||||
|         result = idx._view() | ||||
|         expected = idx | ||||
|  | ||||
|         tm.assert_index_equal(result, expected) | ||||
|  | ||||
|     def test_shallow_copy_disallow_i8(self): | ||||
|         # GH#24391 | ||||
|         pi = period_range("2018-01-01", periods=3, freq="2D") | ||||
|         with pytest.raises(AssertionError, match="ndarray"): | ||||
|             pi._shallow_copy(pi.asi8) | ||||
|  | ||||
|     def test_shallow_copy_requires_disallow_period_index(self): | ||||
|         pi = period_range("2018-01-01", periods=3, freq="2D") | ||||
|         with pytest.raises(AssertionError, match="PeriodIndex"): | ||||
|             pi._shallow_copy(pi) | ||||
|  | ||||
|  | ||||
| class TestSeriesPeriod: | ||||
|     def test_constructor_cant_cast_period(self): | ||||
|         msg = "Cannot cast PeriodIndex to dtype float64" | ||||
|         with pytest.raises(TypeError, match=msg): | ||||
|             Series(period_range("2000-01-01", periods=10, freq="D"), dtype=float) | ||||
|  | ||||
|     def test_constructor_cast_object(self): | ||||
|         pi = period_range("1/1/2000", periods=10) | ||||
|         ser = Series(pi, dtype=PeriodDtype("D")) | ||||
|         exp = Series(pi) | ||||
|         tm.assert_series_equal(ser, exp) | ||||
| @ -0,0 +1,350 @@ | ||||
| from contextlib import nullcontext | ||||
| from datetime import ( | ||||
|     datetime, | ||||
|     time, | ||||
| ) | ||||
| import locale | ||||
|  | ||||
| import numpy as np | ||||
| import pytest | ||||
|  | ||||
| import pandas as pd | ||||
| from pandas import ( | ||||
|     PeriodIndex, | ||||
|     Series, | ||||
| ) | ||||
| import pandas._testing as tm | ||||
|  | ||||
|  | ||||
| def get_local_am_pm(): | ||||
|     """Return the AM and PM strings returned by strftime in current locale.""" | ||||
|     am_local = time(1).strftime("%p") | ||||
|     pm_local = time(13).strftime("%p") | ||||
|     return am_local, pm_local | ||||
|  | ||||
|  | ||||
| def test_get_values_for_csv(): | ||||
|     index = PeriodIndex(["2017-01-01", "2017-01-02", "2017-01-03"], freq="D") | ||||
|  | ||||
|     # First, with no arguments. | ||||
|     expected = np.array(["2017-01-01", "2017-01-02", "2017-01-03"], dtype=object) | ||||
|  | ||||
|     result = index._get_values_for_csv() | ||||
|     tm.assert_numpy_array_equal(result, expected) | ||||
|  | ||||
|     # No NaN values, so na_rep has no effect | ||||
|     result = index._get_values_for_csv(na_rep="pandas") | ||||
|     tm.assert_numpy_array_equal(result, expected) | ||||
|  | ||||
|     # Make sure date formatting works | ||||
|     expected = np.array(["01-2017-01", "01-2017-02", "01-2017-03"], dtype=object) | ||||
|  | ||||
|     result = index._get_values_for_csv(date_format="%m-%Y-%d") | ||||
|     tm.assert_numpy_array_equal(result, expected) | ||||
|  | ||||
|     # NULL object handling should work | ||||
|     index = PeriodIndex(["2017-01-01", pd.NaT, "2017-01-03"], freq="D") | ||||
|     expected = np.array(["2017-01-01", "NaT", "2017-01-03"], dtype=object) | ||||
|  | ||||
|     result = index._get_values_for_csv(na_rep="NaT") | ||||
|     tm.assert_numpy_array_equal(result, expected) | ||||
|  | ||||
|     expected = np.array(["2017-01-01", "pandas", "2017-01-03"], dtype=object) | ||||
|  | ||||
|     result = index._get_values_for_csv(na_rep="pandas") | ||||
|     tm.assert_numpy_array_equal(result, expected) | ||||
|  | ||||
|  | ||||
| class TestPeriodIndexRendering: | ||||
|     def test_format_empty(self): | ||||
|         # GH#35712 | ||||
|         empty_idx = PeriodIndex([], freq="Y") | ||||
|         msg = r"PeriodIndex\.format is deprecated" | ||||
|         with tm.assert_produces_warning(FutureWarning, match=msg): | ||||
|             assert empty_idx.format() == [] | ||||
|         with tm.assert_produces_warning(FutureWarning, match=msg): | ||||
|             assert empty_idx.format(name=True) == [""] | ||||
|  | ||||
|     @pytest.mark.parametrize("method", ["__repr__", "__str__"]) | ||||
|     def test_representation(self, method): | ||||
|         # GH#7601 | ||||
|         idx1 = PeriodIndex([], freq="D") | ||||
|         idx2 = PeriodIndex(["2011-01-01"], freq="D") | ||||
|         idx3 = PeriodIndex(["2011-01-01", "2011-01-02"], freq="D") | ||||
|         idx4 = PeriodIndex(["2011-01-01", "2011-01-02", "2011-01-03"], freq="D") | ||||
|         idx5 = PeriodIndex(["2011", "2012", "2013"], freq="Y") | ||||
|         idx6 = PeriodIndex(["2011-01-01 09:00", "2012-02-01 10:00", "NaT"], freq="h") | ||||
|         idx7 = pd.period_range("2013Q1", periods=1, freq="Q") | ||||
|         idx8 = pd.period_range("2013Q1", periods=2, freq="Q") | ||||
|         idx9 = pd.period_range("2013Q1", periods=3, freq="Q") | ||||
|         idx10 = PeriodIndex(["2011-01-01", "2011-02-01"], freq="3D") | ||||
|  | ||||
|         exp1 = "PeriodIndex([], dtype='period[D]')" | ||||
|  | ||||
|         exp2 = "PeriodIndex(['2011-01-01'], dtype='period[D]')" | ||||
|  | ||||
|         exp3 = "PeriodIndex(['2011-01-01', '2011-01-02'], dtype='period[D]')" | ||||
|  | ||||
|         exp4 = ( | ||||
|             "PeriodIndex(['2011-01-01', '2011-01-02', '2011-01-03'], " | ||||
|             "dtype='period[D]')" | ||||
|         ) | ||||
|  | ||||
|         exp5 = "PeriodIndex(['2011', '2012', '2013'], dtype='period[Y-DEC]')" | ||||
|  | ||||
|         exp6 = ( | ||||
|             "PeriodIndex(['2011-01-01 09:00', '2012-02-01 10:00', 'NaT'], " | ||||
|             "dtype='period[h]')" | ||||
|         ) | ||||
|  | ||||
|         exp7 = "PeriodIndex(['2013Q1'], dtype='period[Q-DEC]')" | ||||
|  | ||||
|         exp8 = "PeriodIndex(['2013Q1', '2013Q2'], dtype='period[Q-DEC]')" | ||||
|  | ||||
|         exp9 = "PeriodIndex(['2013Q1', '2013Q2', '2013Q3'], dtype='period[Q-DEC]')" | ||||
|  | ||||
|         exp10 = "PeriodIndex(['2011-01-01', '2011-02-01'], dtype='period[3D]')" | ||||
|  | ||||
|         for idx, expected in zip( | ||||
|             [idx1, idx2, idx3, idx4, idx5, idx6, idx7, idx8, idx9, idx10], | ||||
|             [exp1, exp2, exp3, exp4, exp5, exp6, exp7, exp8, exp9, exp10], | ||||
|         ): | ||||
|             result = getattr(idx, method)() | ||||
|             assert result == expected | ||||
|  | ||||
|     # TODO: These are Series.__repr__ tests | ||||
|     def test_representation_to_series(self): | ||||
|         # GH#10971 | ||||
|         idx1 = PeriodIndex([], freq="D") | ||||
|         idx2 = PeriodIndex(["2011-01-01"], freq="D") | ||||
|         idx3 = PeriodIndex(["2011-01-01", "2011-01-02"], freq="D") | ||||
|         idx4 = PeriodIndex(["2011-01-01", "2011-01-02", "2011-01-03"], freq="D") | ||||
|         idx5 = PeriodIndex(["2011", "2012", "2013"], freq="Y") | ||||
|         idx6 = PeriodIndex(["2011-01-01 09:00", "2012-02-01 10:00", "NaT"], freq="h") | ||||
|  | ||||
|         idx7 = pd.period_range("2013Q1", periods=1, freq="Q") | ||||
|         idx8 = pd.period_range("2013Q1", periods=2, freq="Q") | ||||
|         idx9 = pd.period_range("2013Q1", periods=3, freq="Q") | ||||
|  | ||||
|         exp1 = """Series([], dtype: period[D])""" | ||||
|  | ||||
|         exp2 = """0    2011-01-01 | ||||
| dtype: period[D]""" | ||||
|  | ||||
|         exp3 = """0    2011-01-01 | ||||
| 1    2011-01-02 | ||||
| dtype: period[D]""" | ||||
|  | ||||
|         exp4 = """0    2011-01-01 | ||||
| 1    2011-01-02 | ||||
| 2    2011-01-03 | ||||
| dtype: period[D]""" | ||||
|  | ||||
|         exp5 = """0    2011 | ||||
| 1    2012 | ||||
| 2    2013 | ||||
| dtype: period[Y-DEC]""" | ||||
|  | ||||
|         exp6 = """0    2011-01-01 09:00 | ||||
| 1    2012-02-01 10:00 | ||||
| 2                 NaT | ||||
| dtype: period[h]""" | ||||
|  | ||||
|         exp7 = """0    2013Q1 | ||||
| dtype: period[Q-DEC]""" | ||||
|  | ||||
|         exp8 = """0    2013Q1 | ||||
| 1    2013Q2 | ||||
| dtype: period[Q-DEC]""" | ||||
|  | ||||
|         exp9 = """0    2013Q1 | ||||
| 1    2013Q2 | ||||
| 2    2013Q3 | ||||
| dtype: period[Q-DEC]""" | ||||
|  | ||||
|         for idx, expected in zip( | ||||
|             [idx1, idx2, idx3, idx4, idx5, idx6, idx7, idx8, idx9], | ||||
|             [exp1, exp2, exp3, exp4, exp5, exp6, exp7, exp8, exp9], | ||||
|         ): | ||||
|             result = repr(Series(idx)) | ||||
|             assert result == expected | ||||
|  | ||||
|     def test_summary(self): | ||||
|         # GH#9116 | ||||
|         idx1 = PeriodIndex([], freq="D") | ||||
|         idx2 = PeriodIndex(["2011-01-01"], freq="D") | ||||
|         idx3 = PeriodIndex(["2011-01-01", "2011-01-02"], freq="D") | ||||
|         idx4 = PeriodIndex(["2011-01-01", "2011-01-02", "2011-01-03"], freq="D") | ||||
|         idx5 = PeriodIndex(["2011", "2012", "2013"], freq="Y") | ||||
|         idx6 = PeriodIndex(["2011-01-01 09:00", "2012-02-01 10:00", "NaT"], freq="h") | ||||
|  | ||||
|         idx7 = pd.period_range("2013Q1", periods=1, freq="Q") | ||||
|         idx8 = pd.period_range("2013Q1", periods=2, freq="Q") | ||||
|         idx9 = pd.period_range("2013Q1", periods=3, freq="Q") | ||||
|  | ||||
|         exp1 = """PeriodIndex: 0 entries | ||||
| Freq: D""" | ||||
|  | ||||
|         exp2 = """PeriodIndex: 1 entries, 2011-01-01 to 2011-01-01 | ||||
| Freq: D""" | ||||
|  | ||||
|         exp3 = """PeriodIndex: 2 entries, 2011-01-01 to 2011-01-02 | ||||
| Freq: D""" | ||||
|  | ||||
|         exp4 = """PeriodIndex: 3 entries, 2011-01-01 to 2011-01-03 | ||||
| Freq: D""" | ||||
|  | ||||
|         exp5 = """PeriodIndex: 3 entries, 2011 to 2013 | ||||
| Freq: Y-DEC""" | ||||
|  | ||||
|         exp6 = """PeriodIndex: 3 entries, 2011-01-01 09:00 to NaT | ||||
| Freq: h""" | ||||
|  | ||||
|         exp7 = """PeriodIndex: 1 entries, 2013Q1 to 2013Q1 | ||||
| Freq: Q-DEC""" | ||||
|  | ||||
|         exp8 = """PeriodIndex: 2 entries, 2013Q1 to 2013Q2 | ||||
| Freq: Q-DEC""" | ||||
|  | ||||
|         exp9 = """PeriodIndex: 3 entries, 2013Q1 to 2013Q3 | ||||
| Freq: Q-DEC""" | ||||
|  | ||||
|         for idx, expected in zip( | ||||
|             [idx1, idx2, idx3, idx4, idx5, idx6, idx7, idx8, idx9], | ||||
|             [exp1, exp2, exp3, exp4, exp5, exp6, exp7, exp8, exp9], | ||||
|         ): | ||||
|             result = idx._summary() | ||||
|             assert result == expected | ||||
|  | ||||
|  | ||||
| class TestPeriodIndexFormat: | ||||
|     def test_period_format_and_strftime_default(self): | ||||
|         per = PeriodIndex([datetime(2003, 1, 1, 12), None], freq="h") | ||||
|  | ||||
|         # Default formatting | ||||
|         msg = "PeriodIndex.format is deprecated" | ||||
|         with tm.assert_produces_warning(FutureWarning, match=msg): | ||||
|             formatted = per.format() | ||||
|         assert formatted[0] == "2003-01-01 12:00"  # default: minutes not shown | ||||
|         assert formatted[1] == "NaT" | ||||
|         # format is equivalent to strftime(None)... | ||||
|         assert formatted[0] == per.strftime(None)[0] | ||||
|         assert per.strftime(None)[1] is np.nan  # ...except for NaTs | ||||
|  | ||||
|         # Same test with nanoseconds freq | ||||
|         per = pd.period_range("2003-01-01 12:01:01.123456789", periods=2, freq="ns") | ||||
|         with tm.assert_produces_warning(FutureWarning, match=msg): | ||||
|             formatted = per.format() | ||||
|         assert (formatted == per.strftime(None)).all() | ||||
|         assert formatted[0] == "2003-01-01 12:01:01.123456789" | ||||
|         assert formatted[1] == "2003-01-01 12:01:01.123456790" | ||||
|  | ||||
|     def test_period_custom(self): | ||||
|         # GH#46252 custom formatting directives %l (ms) and %u (us) | ||||
|         msg = "PeriodIndex.format is deprecated" | ||||
|  | ||||
|         # 3 digits | ||||
|         per = pd.period_range("2003-01-01 12:01:01.123", periods=2, freq="ms") | ||||
|         with tm.assert_produces_warning(FutureWarning, match=msg): | ||||
|             formatted = per.format(date_format="%y %I:%M:%S (ms=%l us=%u ns=%n)") | ||||
|         assert formatted[0] == "03 12:01:01 (ms=123 us=123000 ns=123000000)" | ||||
|         assert formatted[1] == "03 12:01:01 (ms=124 us=124000 ns=124000000)" | ||||
|  | ||||
|         # 6 digits | ||||
|         per = pd.period_range("2003-01-01 12:01:01.123456", periods=2, freq="us") | ||||
|         with tm.assert_produces_warning(FutureWarning, match=msg): | ||||
|             formatted = per.format(date_format="%y %I:%M:%S (ms=%l us=%u ns=%n)") | ||||
|         assert formatted[0] == "03 12:01:01 (ms=123 us=123456 ns=123456000)" | ||||
|         assert formatted[1] == "03 12:01:01 (ms=123 us=123457 ns=123457000)" | ||||
|  | ||||
|         # 9 digits | ||||
|         per = pd.period_range("2003-01-01 12:01:01.123456789", periods=2, freq="ns") | ||||
|         with tm.assert_produces_warning(FutureWarning, match=msg): | ||||
|             formatted = per.format(date_format="%y %I:%M:%S (ms=%l us=%u ns=%n)") | ||||
|         assert formatted[0] == "03 12:01:01 (ms=123 us=123456 ns=123456789)" | ||||
|         assert formatted[1] == "03 12:01:01 (ms=123 us=123456 ns=123456790)" | ||||
|  | ||||
|     def test_period_tz(self): | ||||
|         # Formatting periods created from a datetime with timezone. | ||||
|         msg = r"PeriodIndex\.format is deprecated" | ||||
|         # This timestamp is in 2013 in Europe/Paris but is 2012 in UTC | ||||
|         dt = pd.to_datetime(["2013-01-01 00:00:00+01:00"], utc=True) | ||||
|  | ||||
|         # Converting to a period looses the timezone information | ||||
|         # Since tz is currently set as utc, we'll see 2012 | ||||
|         with tm.assert_produces_warning(UserWarning, match="will drop timezone"): | ||||
|             per = dt.to_period(freq="h") | ||||
|         with tm.assert_produces_warning(FutureWarning, match=msg): | ||||
|             assert per.format()[0] == "2012-12-31 23:00" | ||||
|  | ||||
|         # If tz is currently set as paris before conversion, we'll see 2013 | ||||
|         dt = dt.tz_convert("Europe/Paris") | ||||
|         with tm.assert_produces_warning(UserWarning, match="will drop timezone"): | ||||
|             per = dt.to_period(freq="h") | ||||
|         with tm.assert_produces_warning(FutureWarning, match=msg): | ||||
|             assert per.format()[0] == "2013-01-01 00:00" | ||||
|  | ||||
|     @pytest.mark.parametrize( | ||||
|         "locale_str", | ||||
|         [ | ||||
|             pytest.param(None, id=str(locale.getlocale())), | ||||
|             "it_IT.utf8", | ||||
|             "it_IT",  # Note: encoding will be 'ISO8859-1' | ||||
|             "zh_CN.utf8", | ||||
|             "zh_CN",  # Note: encoding will be 'gb2312' | ||||
|         ], | ||||
|     ) | ||||
|     def test_period_non_ascii_fmt(self, locale_str): | ||||
|         # GH#46468 non-ascii char in input format string leads to wrong output | ||||
|  | ||||
|         # Skip if locale cannot be set | ||||
|         if locale_str is not None and not tm.can_set_locale(locale_str, locale.LC_ALL): | ||||
|             pytest.skip(f"Skipping as locale '{locale_str}' cannot be set on host.") | ||||
|  | ||||
|         # Change locale temporarily for this test. | ||||
|         with tm.set_locale(locale_str, locale.LC_ALL) if locale_str else nullcontext(): | ||||
|             # Scalar | ||||
|             per = pd.Period("2018-03-11 13:00", freq="h") | ||||
|             assert per.strftime("%y é") == "18 é" | ||||
|  | ||||
|             # Index | ||||
|             per = pd.period_range("2003-01-01 01:00:00", periods=2, freq="12h") | ||||
|             msg = "PeriodIndex.format is deprecated" | ||||
|             with tm.assert_produces_warning(FutureWarning, match=msg): | ||||
|                 formatted = per.format(date_format="%y é") | ||||
|             assert formatted[0] == "03 é" | ||||
|             assert formatted[1] == "03 é" | ||||
|  | ||||
|     @pytest.mark.parametrize( | ||||
|         "locale_str", | ||||
|         [ | ||||
|             pytest.param(None, id=str(locale.getlocale())), | ||||
|             "it_IT.utf8", | ||||
|             "it_IT",  # Note: encoding will be 'ISO8859-1' | ||||
|             "zh_CN.utf8", | ||||
|             "zh_CN",  # Note: encoding will be 'gb2312' | ||||
|         ], | ||||
|     ) | ||||
|     def test_period_custom_locale_directive(self, locale_str): | ||||
|         # GH#46319 locale-specific directive leads to non-utf8 c strftime char* result | ||||
|  | ||||
|         # Skip if locale cannot be set | ||||
|         if locale_str is not None and not tm.can_set_locale(locale_str, locale.LC_ALL): | ||||
|             pytest.skip(f"Skipping as locale '{locale_str}' cannot be set on host.") | ||||
|  | ||||
|         # Change locale temporarily for this test. | ||||
|         with tm.set_locale(locale_str, locale.LC_ALL) if locale_str else nullcontext(): | ||||
|             # Get locale-specific reference | ||||
|             am_local, pm_local = get_local_am_pm() | ||||
|  | ||||
|             # Scalar | ||||
|             per = pd.Period("2018-03-11 13:00", freq="h") | ||||
|             assert per.strftime("%p") == pm_local | ||||
|  | ||||
|             # Index | ||||
|             per = pd.period_range("2003-01-01 01:00:00", periods=2, freq="12h") | ||||
|             msg = "PeriodIndex.format is deprecated" | ||||
|             with tm.assert_produces_warning(FutureWarning, match=msg): | ||||
|                 formatted = per.format(date_format="%y %I:%M:%S%p") | ||||
|             assert formatted[0] == f"03 01:00:00{am_local}" | ||||
|             assert formatted[1] == f"03 01:00:00{pm_local}" | ||||
| @ -0,0 +1,28 @@ | ||||
| import pytest | ||||
|  | ||||
| from pandas.compat import PY311 | ||||
|  | ||||
| from pandas import ( | ||||
|     offsets, | ||||
|     period_range, | ||||
| ) | ||||
| import pandas._testing as tm | ||||
|  | ||||
|  | ||||
| class TestFreq: | ||||
|     def test_freq_setter_deprecated(self): | ||||
|         # GH#20678 | ||||
|         idx = period_range("2018Q1", periods=4, freq="Q") | ||||
|  | ||||
|         # no warning for getter | ||||
|         with tm.assert_produces_warning(None): | ||||
|             idx.freq | ||||
|  | ||||
|         # warning for setter | ||||
|         msg = ( | ||||
|             "property 'freq' of 'PeriodArray' object has no setter" | ||||
|             if PY311 | ||||
|             else "can't set attribute" | ||||
|         ) | ||||
|         with pytest.raises(AttributeError, match=msg): | ||||
|             idx.freq = offsets.Day() | ||||
| @ -0,0 +1,815 @@ | ||||
| from datetime import datetime | ||||
| import re | ||||
|  | ||||
| import numpy as np | ||||
| import pytest | ||||
|  | ||||
| from pandas._libs.tslibs import period as libperiod | ||||
| from pandas.errors import InvalidIndexError | ||||
|  | ||||
| import pandas as pd | ||||
| from pandas import ( | ||||
|     DatetimeIndex, | ||||
|     NaT, | ||||
|     Period, | ||||
|     PeriodIndex, | ||||
|     Series, | ||||
|     Timedelta, | ||||
|     date_range, | ||||
|     notna, | ||||
|     period_range, | ||||
| ) | ||||
| import pandas._testing as tm | ||||
|  | ||||
| dti4 = date_range("2016-01-01", periods=4) | ||||
| dti = dti4[:-1] | ||||
| rng = pd.Index(range(3)) | ||||
|  | ||||
|  | ||||
| @pytest.fixture( | ||||
|     params=[ | ||||
|         dti, | ||||
|         dti.tz_localize("UTC"), | ||||
|         dti.to_period("W"), | ||||
|         dti - dti[0], | ||||
|         rng, | ||||
|         pd.Index([1, 2, 3]), | ||||
|         pd.Index([2.0, 3.0, 4.0]), | ||||
|         pd.Index([4, 5, 6], dtype="u8"), | ||||
|         pd.IntervalIndex.from_breaks(dti4), | ||||
|     ] | ||||
| ) | ||||
| def non_comparable_idx(request): | ||||
|     # All have length 3 | ||||
|     return request.param | ||||
|  | ||||
|  | ||||
| class TestGetItem: | ||||
|     def test_getitem_slice_keeps_name(self): | ||||
|         idx = period_range("20010101", periods=10, freq="D", name="bob") | ||||
|         assert idx.name == idx[1:].name | ||||
|  | ||||
|     def test_getitem(self): | ||||
|         idx1 = period_range("2011-01-01", "2011-01-31", freq="D", name="idx") | ||||
|  | ||||
|         for idx in [idx1]: | ||||
|             result = idx[0] | ||||
|             assert result == Period("2011-01-01", freq="D") | ||||
|  | ||||
|             result = idx[-1] | ||||
|             assert result == Period("2011-01-31", freq="D") | ||||
|  | ||||
|             result = idx[0:5] | ||||
|             expected = period_range("2011-01-01", "2011-01-05", freq="D", name="idx") | ||||
|             tm.assert_index_equal(result, expected) | ||||
|             assert result.freq == expected.freq | ||||
|             assert result.freq == "D" | ||||
|  | ||||
|             result = idx[0:10:2] | ||||
|             expected = PeriodIndex( | ||||
|                 ["2011-01-01", "2011-01-03", "2011-01-05", "2011-01-07", "2011-01-09"], | ||||
|                 freq="D", | ||||
|                 name="idx", | ||||
|             ) | ||||
|             tm.assert_index_equal(result, expected) | ||||
|             assert result.freq == expected.freq | ||||
|             assert result.freq == "D" | ||||
|  | ||||
|             result = idx[-20:-5:3] | ||||
|             expected = PeriodIndex( | ||||
|                 ["2011-01-12", "2011-01-15", "2011-01-18", "2011-01-21", "2011-01-24"], | ||||
|                 freq="D", | ||||
|                 name="idx", | ||||
|             ) | ||||
|             tm.assert_index_equal(result, expected) | ||||
|             assert result.freq == expected.freq | ||||
|             assert result.freq == "D" | ||||
|  | ||||
|             result = idx[4::-1] | ||||
|             expected = PeriodIndex( | ||||
|                 ["2011-01-05", "2011-01-04", "2011-01-03", "2011-01-02", "2011-01-01"], | ||||
|                 freq="D", | ||||
|                 name="idx", | ||||
|             ) | ||||
|             tm.assert_index_equal(result, expected) | ||||
|             assert result.freq == expected.freq | ||||
|             assert result.freq == "D" | ||||
|  | ||||
|     def test_getitem_index(self): | ||||
|         idx = period_range("2007-01", periods=10, freq="M", name="x") | ||||
|  | ||||
|         result = idx[[1, 3, 5]] | ||||
|         exp = PeriodIndex(["2007-02", "2007-04", "2007-06"], freq="M", name="x") | ||||
|         tm.assert_index_equal(result, exp) | ||||
|  | ||||
|         result = idx[[True, True, False, False, False, True, True, False, False, False]] | ||||
|         exp = PeriodIndex( | ||||
|             ["2007-01", "2007-02", "2007-06", "2007-07"], freq="M", name="x" | ||||
|         ) | ||||
|         tm.assert_index_equal(result, exp) | ||||
|  | ||||
|     def test_getitem_partial(self): | ||||
|         rng = period_range("2007-01", periods=50, freq="M") | ||||
|         ts = Series(np.random.default_rng(2).standard_normal(len(rng)), rng) | ||||
|  | ||||
|         with pytest.raises(KeyError, match=r"^'2006'$"): | ||||
|             ts["2006"] | ||||
|  | ||||
|         result = ts["2008"] | ||||
|         assert (result.index.year == 2008).all() | ||||
|  | ||||
|         result = ts["2008":"2009"] | ||||
|         assert len(result) == 24 | ||||
|  | ||||
|         result = ts["2008-1":"2009-12"] | ||||
|         assert len(result) == 24 | ||||
|  | ||||
|         result = ts["2008Q1":"2009Q4"] | ||||
|         assert len(result) == 24 | ||||
|  | ||||
|         result = ts[:"2009"] | ||||
|         assert len(result) == 36 | ||||
|  | ||||
|         result = ts["2009":] | ||||
|         assert len(result) == 50 - 24 | ||||
|  | ||||
|         exp = result | ||||
|         result = ts[24:] | ||||
|         tm.assert_series_equal(exp, result) | ||||
|  | ||||
|         ts = pd.concat([ts[10:], ts[10:]]) | ||||
|         msg = "left slice bound for non-unique label: '2008'" | ||||
|         with pytest.raises(KeyError, match=msg): | ||||
|             ts[slice("2008", "2009")] | ||||
|  | ||||
|     def test_getitem_datetime(self): | ||||
|         rng = period_range(start="2012-01-01", periods=10, freq="W-MON") | ||||
|         ts = Series(range(len(rng)), index=rng) | ||||
|  | ||||
|         dt1 = datetime(2011, 10, 2) | ||||
|         dt4 = datetime(2012, 4, 20) | ||||
|  | ||||
|         rs = ts[dt1:dt4] | ||||
|         tm.assert_series_equal(rs, ts) | ||||
|  | ||||
|     def test_getitem_nat(self): | ||||
|         idx = PeriodIndex(["2011-01", "NaT", "2011-02"], freq="M") | ||||
|         assert idx[0] == Period("2011-01", freq="M") | ||||
|         assert idx[1] is NaT | ||||
|  | ||||
|         s = Series([0, 1, 2], index=idx) | ||||
|         assert s[NaT] == 1 | ||||
|  | ||||
|         s = Series(idx, index=idx) | ||||
|         assert s[Period("2011-01", freq="M")] == Period("2011-01", freq="M") | ||||
|         assert s[NaT] is NaT | ||||
|  | ||||
|     def test_getitem_list_periods(self): | ||||
|         # GH 7710 | ||||
|         rng = period_range(start="2012-01-01", periods=10, freq="D") | ||||
|         ts = Series(range(len(rng)), index=rng) | ||||
|         exp = ts.iloc[[1]] | ||||
|         tm.assert_series_equal(ts[[Period("2012-01-02", freq="D")]], exp) | ||||
|  | ||||
|     @pytest.mark.arm_slow | ||||
|     def test_getitem_seconds(self): | ||||
|         # GH#6716 | ||||
|         didx = date_range(start="2013/01/01 09:00:00", freq="s", periods=4000) | ||||
|         pidx = period_range(start="2013/01/01 09:00:00", freq="s", periods=4000) | ||||
|  | ||||
|         for idx in [didx, pidx]: | ||||
|             # getitem against index should raise ValueError | ||||
|             values = [ | ||||
|                 "2014", | ||||
|                 "2013/02", | ||||
|                 "2013/01/02", | ||||
|                 "2013/02/01 9h", | ||||
|                 "2013/02/01 09:00", | ||||
|             ] | ||||
|             for val in values: | ||||
|                 # GH7116 | ||||
|                 # these show deprecations as we are trying | ||||
|                 # to slice with non-integer indexers | ||||
|                 with pytest.raises(IndexError, match="only integers, slices"): | ||||
|                     idx[val] | ||||
|  | ||||
|             ser = Series(np.random.default_rng(2).random(len(idx)), index=idx) | ||||
|             tm.assert_series_equal(ser["2013/01/01 10:00"], ser[3600:3660]) | ||||
|             tm.assert_series_equal(ser["2013/01/01 9h"], ser[:3600]) | ||||
|             for d in ["2013/01/01", "2013/01", "2013"]: | ||||
|                 tm.assert_series_equal(ser[d], ser) | ||||
|  | ||||
|     @pytest.mark.parametrize( | ||||
|         "idx_range", | ||||
|         [ | ||||
|             date_range, | ||||
|             period_range, | ||||
|         ], | ||||
|     ) | ||||
|     def test_getitem_day(self, idx_range): | ||||
|         # GH#6716 | ||||
|         # Confirm DatetimeIndex and PeriodIndex works identically | ||||
|         # getitem against index should raise ValueError | ||||
|         idx = idx_range(start="2013/01/01", freq="D", periods=400) | ||||
|         values = [ | ||||
|             "2014", | ||||
|             "2013/02", | ||||
|             "2013/01/02", | ||||
|             "2013/02/01 9h", | ||||
|             "2013/02/01 09:00", | ||||
|         ] | ||||
|         for val in values: | ||||
|             # GH7116 | ||||
|             # these show deprecations as we are trying | ||||
|             # to slice with non-integer indexers | ||||
|             with pytest.raises(IndexError, match="only integers, slices"): | ||||
|                 idx[val] | ||||
|  | ||||
|         ser = Series(np.random.default_rng(2).random(len(idx)), index=idx) | ||||
|         tm.assert_series_equal(ser["2013/01"], ser[0:31]) | ||||
|         tm.assert_series_equal(ser["2013/02"], ser[31:59]) | ||||
|         tm.assert_series_equal(ser["2014"], ser[365:]) | ||||
|  | ||||
|         invalid = ["2013/02/01 9h", "2013/02/01 09:00"] | ||||
|         for val in invalid: | ||||
|             with pytest.raises(KeyError, match=val): | ||||
|                 ser[val] | ||||
|  | ||||
|  | ||||
| class TestGetLoc: | ||||
|     def test_get_loc_msg(self): | ||||
|         idx = period_range("2000-1-1", freq="Y", periods=10) | ||||
|         bad_period = Period("2012", "Y") | ||||
|         with pytest.raises(KeyError, match=r"^Period\('2012', 'Y-DEC'\)$"): | ||||
|             idx.get_loc(bad_period) | ||||
|  | ||||
|         try: | ||||
|             idx.get_loc(bad_period) | ||||
|         except KeyError as inst: | ||||
|             assert inst.args[0] == bad_period | ||||
|  | ||||
|     def test_get_loc_nat(self): | ||||
|         didx = DatetimeIndex(["2011-01-01", "NaT", "2011-01-03"]) | ||||
|         pidx = PeriodIndex(["2011-01-01", "NaT", "2011-01-03"], freq="M") | ||||
|  | ||||
|         # check DatetimeIndex compat | ||||
|         for idx in [didx, pidx]: | ||||
|             assert idx.get_loc(NaT) == 1 | ||||
|             assert idx.get_loc(None) == 1 | ||||
|             assert idx.get_loc(float("nan")) == 1 | ||||
|             assert idx.get_loc(np.nan) == 1 | ||||
|  | ||||
|     def test_get_loc(self): | ||||
|         # GH 17717 | ||||
|         p0 = Period("2017-09-01") | ||||
|         p1 = Period("2017-09-02") | ||||
|         p2 = Period("2017-09-03") | ||||
|  | ||||
|         # get the location of p1/p2 from | ||||
|         # monotonic increasing PeriodIndex with non-duplicate | ||||
|         idx0 = PeriodIndex([p0, p1, p2]) | ||||
|         expected_idx1_p1 = 1 | ||||
|         expected_idx1_p2 = 2 | ||||
|  | ||||
|         assert idx0.get_loc(p1) == expected_idx1_p1 | ||||
|         assert idx0.get_loc(str(p1)) == expected_idx1_p1 | ||||
|         assert idx0.get_loc(p2) == expected_idx1_p2 | ||||
|         assert idx0.get_loc(str(p2)) == expected_idx1_p2 | ||||
|  | ||||
|         msg = "Cannot interpret 'foo' as period" | ||||
|         with pytest.raises(KeyError, match=msg): | ||||
|             idx0.get_loc("foo") | ||||
|         with pytest.raises(KeyError, match=r"^1\.1$"): | ||||
|             idx0.get_loc(1.1) | ||||
|  | ||||
|         with pytest.raises(InvalidIndexError, match=re.escape(str(idx0))): | ||||
|             idx0.get_loc(idx0) | ||||
|  | ||||
|         # get the location of p1/p2 from | ||||
|         # monotonic increasing PeriodIndex with duplicate | ||||
|         idx1 = PeriodIndex([p1, p1, p2]) | ||||
|         expected_idx1_p1 = slice(0, 2) | ||||
|         expected_idx1_p2 = 2 | ||||
|  | ||||
|         assert idx1.get_loc(p1) == expected_idx1_p1 | ||||
|         assert idx1.get_loc(str(p1)) == expected_idx1_p1 | ||||
|         assert idx1.get_loc(p2) == expected_idx1_p2 | ||||
|         assert idx1.get_loc(str(p2)) == expected_idx1_p2 | ||||
|  | ||||
|         msg = "Cannot interpret 'foo' as period" | ||||
|         with pytest.raises(KeyError, match=msg): | ||||
|             idx1.get_loc("foo") | ||||
|  | ||||
|         with pytest.raises(KeyError, match=r"^1\.1$"): | ||||
|             idx1.get_loc(1.1) | ||||
|  | ||||
|         with pytest.raises(InvalidIndexError, match=re.escape(str(idx1))): | ||||
|             idx1.get_loc(idx1) | ||||
|  | ||||
|         # get the location of p1/p2 from | ||||
|         # non-monotonic increasing/decreasing PeriodIndex with duplicate | ||||
|         idx2 = PeriodIndex([p2, p1, p2]) | ||||
|         expected_idx2_p1 = 1 | ||||
|         expected_idx2_p2 = np.array([True, False, True]) | ||||
|  | ||||
|         assert idx2.get_loc(p1) == expected_idx2_p1 | ||||
|         assert idx2.get_loc(str(p1)) == expected_idx2_p1 | ||||
|         tm.assert_numpy_array_equal(idx2.get_loc(p2), expected_idx2_p2) | ||||
|         tm.assert_numpy_array_equal(idx2.get_loc(str(p2)), expected_idx2_p2) | ||||
|  | ||||
|     def test_get_loc_integer(self): | ||||
|         dti = date_range("2016-01-01", periods=3) | ||||
|         pi = dti.to_period("D") | ||||
|         with pytest.raises(KeyError, match="16801"): | ||||
|             pi.get_loc(16801) | ||||
|  | ||||
|         pi2 = dti.to_period("Y")  # duplicates, ordinals are all 46 | ||||
|         with pytest.raises(KeyError, match="46"): | ||||
|             pi2.get_loc(46) | ||||
|  | ||||
|     def test_get_loc_invalid_string_raises_keyerror(self): | ||||
|         # GH#34240 | ||||
|         pi = period_range("2000", periods=3, name="A") | ||||
|         with pytest.raises(KeyError, match="A"): | ||||
|             pi.get_loc("A") | ||||
|  | ||||
|         ser = Series([1, 2, 3], index=pi) | ||||
|         with pytest.raises(KeyError, match="A"): | ||||
|             ser.loc["A"] | ||||
|  | ||||
|         with pytest.raises(KeyError, match="A"): | ||||
|             ser["A"] | ||||
|  | ||||
|         assert "A" not in ser | ||||
|         assert "A" not in pi | ||||
|  | ||||
|     def test_get_loc_mismatched_freq(self): | ||||
|         # see also test_get_indexer_mismatched_dtype testing we get analogous | ||||
|         # behavior for get_loc | ||||
|         dti = date_range("2016-01-01", periods=3) | ||||
|         pi = dti.to_period("D") | ||||
|         pi2 = dti.to_period("W") | ||||
|         pi3 = pi.view(pi2.dtype)  # i.e. matching i8 representations | ||||
|  | ||||
|         with pytest.raises(KeyError, match="W-SUN"): | ||||
|             pi.get_loc(pi2[0]) | ||||
|  | ||||
|         with pytest.raises(KeyError, match="W-SUN"): | ||||
|             # even though we have matching i8 values | ||||
|             pi.get_loc(pi3[0]) | ||||
|  | ||||
|  | ||||
| class TestGetIndexer: | ||||
|     def test_get_indexer(self): | ||||
|         # GH 17717 | ||||
|         p1 = Period("2017-09-01") | ||||
|         p2 = Period("2017-09-04") | ||||
|         p3 = Period("2017-09-07") | ||||
|  | ||||
|         tp0 = Period("2017-08-31") | ||||
|         tp1 = Period("2017-09-02") | ||||
|         tp2 = Period("2017-09-05") | ||||
|         tp3 = Period("2017-09-09") | ||||
|  | ||||
|         idx = PeriodIndex([p1, p2, p3]) | ||||
|  | ||||
|         tm.assert_numpy_array_equal( | ||||
|             idx.get_indexer(idx), np.array([0, 1, 2], dtype=np.intp) | ||||
|         ) | ||||
|  | ||||
|         target = PeriodIndex([tp0, tp1, tp2, tp3]) | ||||
|         tm.assert_numpy_array_equal( | ||||
|             idx.get_indexer(target, "pad"), np.array([-1, 0, 1, 2], dtype=np.intp) | ||||
|         ) | ||||
|         tm.assert_numpy_array_equal( | ||||
|             idx.get_indexer(target, "backfill"), np.array([0, 1, 2, -1], dtype=np.intp) | ||||
|         ) | ||||
|         tm.assert_numpy_array_equal( | ||||
|             idx.get_indexer(target, "nearest"), np.array([0, 0, 1, 2], dtype=np.intp) | ||||
|         ) | ||||
|  | ||||
|         res = idx.get_indexer(target, "nearest", tolerance=Timedelta("1 day")) | ||||
|         tm.assert_numpy_array_equal(res, np.array([0, 0, 1, -1], dtype=np.intp)) | ||||
|  | ||||
|     def test_get_indexer_mismatched_dtype(self): | ||||
|         # Check that we return all -1s and do not raise or cast incorrectly | ||||
|  | ||||
|         dti = date_range("2016-01-01", periods=3) | ||||
|         pi = dti.to_period("D") | ||||
|         pi2 = dti.to_period("W") | ||||
|  | ||||
|         expected = np.array([-1, -1, -1], dtype=np.intp) | ||||
|  | ||||
|         result = pi.get_indexer(dti) | ||||
|         tm.assert_numpy_array_equal(result, expected) | ||||
|  | ||||
|         # This should work in both directions | ||||
|         result = dti.get_indexer(pi) | ||||
|         tm.assert_numpy_array_equal(result, expected) | ||||
|  | ||||
|         result = pi.get_indexer(pi2) | ||||
|         tm.assert_numpy_array_equal(result, expected) | ||||
|  | ||||
|         # We expect the same from get_indexer_non_unique | ||||
|         result = pi.get_indexer_non_unique(dti)[0] | ||||
|         tm.assert_numpy_array_equal(result, expected) | ||||
|  | ||||
|         result = dti.get_indexer_non_unique(pi)[0] | ||||
|         tm.assert_numpy_array_equal(result, expected) | ||||
|  | ||||
|         result = pi.get_indexer_non_unique(pi2)[0] | ||||
|         tm.assert_numpy_array_equal(result, expected) | ||||
|  | ||||
|     def test_get_indexer_mismatched_dtype_different_length(self, non_comparable_idx): | ||||
|         # without method we aren't checking inequalities, so get all-missing | ||||
|         #  but do not raise | ||||
|         dti = date_range("2016-01-01", periods=3) | ||||
|         pi = dti.to_period("D") | ||||
|  | ||||
|         other = non_comparable_idx | ||||
|  | ||||
|         res = pi[:-1].get_indexer(other) | ||||
|         expected = -np.ones(other.shape, dtype=np.intp) | ||||
|         tm.assert_numpy_array_equal(res, expected) | ||||
|  | ||||
|     @pytest.mark.parametrize("method", ["pad", "backfill", "nearest"]) | ||||
|     def test_get_indexer_mismatched_dtype_with_method(self, non_comparable_idx, method): | ||||
|         dti = date_range("2016-01-01", periods=3) | ||||
|         pi = dti.to_period("D") | ||||
|  | ||||
|         other = non_comparable_idx | ||||
|  | ||||
|         msg = re.escape(f"Cannot compare dtypes {pi.dtype} and {other.dtype}") | ||||
|         with pytest.raises(TypeError, match=msg): | ||||
|             pi.get_indexer(other, method=method) | ||||
|  | ||||
|         for dtype in ["object", "category"]: | ||||
|             other2 = other.astype(dtype) | ||||
|             if dtype == "object" and isinstance(other, PeriodIndex): | ||||
|                 continue | ||||
|             # Two different error message patterns depending on dtypes | ||||
|             msg = "|".join( | ||||
|                 [ | ||||
|                     re.escape(msg) | ||||
|                     for msg in ( | ||||
|                         f"Cannot compare dtypes {pi.dtype} and {other.dtype}", | ||||
|                         " not supported between instances of ", | ||||
|                     ) | ||||
|                 ] | ||||
|             ) | ||||
|             with pytest.raises(TypeError, match=msg): | ||||
|                 pi.get_indexer(other2, method=method) | ||||
|  | ||||
|     def test_get_indexer_non_unique(self): | ||||
|         # GH 17717 | ||||
|         p1 = Period("2017-09-02") | ||||
|         p2 = Period("2017-09-03") | ||||
|         p3 = Period("2017-09-04") | ||||
|         p4 = Period("2017-09-05") | ||||
|  | ||||
|         idx1 = PeriodIndex([p1, p2, p1]) | ||||
|         idx2 = PeriodIndex([p2, p1, p3, p4]) | ||||
|  | ||||
|         result = idx1.get_indexer_non_unique(idx2) | ||||
|         expected_indexer = np.array([1, 0, 2, -1, -1], dtype=np.intp) | ||||
|         expected_missing = np.array([2, 3], dtype=np.intp) | ||||
|  | ||||
|         tm.assert_numpy_array_equal(result[0], expected_indexer) | ||||
|         tm.assert_numpy_array_equal(result[1], expected_missing) | ||||
|  | ||||
|     # TODO: This method came from test_period; de-dup with version above | ||||
|     def test_get_indexer2(self): | ||||
|         idx = period_range("2000-01-01", periods=3).asfreq("h", how="start") | ||||
|         tm.assert_numpy_array_equal( | ||||
|             idx.get_indexer(idx), np.array([0, 1, 2], dtype=np.intp) | ||||
|         ) | ||||
|  | ||||
|         target = PeriodIndex( | ||||
|             ["1999-12-31T23", "2000-01-01T12", "2000-01-02T01"], freq="h" | ||||
|         ) | ||||
|         tm.assert_numpy_array_equal( | ||||
|             idx.get_indexer(target, "pad"), np.array([-1, 0, 1], dtype=np.intp) | ||||
|         ) | ||||
|         tm.assert_numpy_array_equal( | ||||
|             idx.get_indexer(target, "backfill"), np.array([0, 1, 2], dtype=np.intp) | ||||
|         ) | ||||
|         tm.assert_numpy_array_equal( | ||||
|             idx.get_indexer(target, "nearest"), np.array([0, 1, 1], dtype=np.intp) | ||||
|         ) | ||||
|         tm.assert_numpy_array_equal( | ||||
|             idx.get_indexer(target, "nearest", tolerance="1 hour"), | ||||
|             np.array([0, -1, 1], dtype=np.intp), | ||||
|         ) | ||||
|  | ||||
|         msg = "Input has different freq=None from PeriodArray\\(freq=h\\)" | ||||
|         with pytest.raises(ValueError, match=msg): | ||||
|             idx.get_indexer(target, "nearest", tolerance="1 minute") | ||||
|  | ||||
|         tm.assert_numpy_array_equal( | ||||
|             idx.get_indexer(target, "nearest", tolerance="1 day"), | ||||
|             np.array([0, 1, 1], dtype=np.intp), | ||||
|         ) | ||||
|         tol_raw = [ | ||||
|             Timedelta("1 hour"), | ||||
|             Timedelta("1 hour"), | ||||
|             np.timedelta64(1, "D"), | ||||
|         ] | ||||
|         tm.assert_numpy_array_equal( | ||||
|             idx.get_indexer( | ||||
|                 target, "nearest", tolerance=[np.timedelta64(x) for x in tol_raw] | ||||
|             ), | ||||
|             np.array([0, -1, 1], dtype=np.intp), | ||||
|         ) | ||||
|         tol_bad = [ | ||||
|             Timedelta("2 hour").to_timedelta64(), | ||||
|             Timedelta("1 hour").to_timedelta64(), | ||||
|             np.timedelta64(1, "M"), | ||||
|         ] | ||||
|         with pytest.raises( | ||||
|             libperiod.IncompatibleFrequency, match="Input has different freq=None from" | ||||
|         ): | ||||
|             idx.get_indexer(target, "nearest", tolerance=tol_bad) | ||||
|  | ||||
|  | ||||
| class TestWhere: | ||||
|     def test_where(self, listlike_box): | ||||
|         i = period_range("20130101", periods=5, freq="D") | ||||
|         cond = [True] * len(i) | ||||
|         expected = i | ||||
|         result = i.where(listlike_box(cond)) | ||||
|         tm.assert_index_equal(result, expected) | ||||
|  | ||||
|         cond = [False] + [True] * (len(i) - 1) | ||||
|         expected = PeriodIndex([NaT] + i[1:].tolist(), freq="D") | ||||
|         result = i.where(listlike_box(cond)) | ||||
|         tm.assert_index_equal(result, expected) | ||||
|  | ||||
|     def test_where_other(self): | ||||
|         i = period_range("20130101", periods=5, freq="D") | ||||
|         for arr in [np.nan, NaT]: | ||||
|             result = i.where(notna(i), other=arr) | ||||
|             expected = i | ||||
|             tm.assert_index_equal(result, expected) | ||||
|  | ||||
|         i2 = i.copy() | ||||
|         i2 = PeriodIndex([NaT, NaT] + i[2:].tolist(), freq="D") | ||||
|         result = i.where(notna(i2), i2) | ||||
|         tm.assert_index_equal(result, i2) | ||||
|  | ||||
|         i2 = i.copy() | ||||
|         i2 = PeriodIndex([NaT, NaT] + i[2:].tolist(), freq="D") | ||||
|         result = i.where(notna(i2), i2.values) | ||||
|         tm.assert_index_equal(result, i2) | ||||
|  | ||||
|     def test_where_invalid_dtypes(self): | ||||
|         pi = period_range("20130101", periods=5, freq="D") | ||||
|  | ||||
|         tail = pi[2:].tolist() | ||||
|         i2 = PeriodIndex([NaT, NaT] + tail, freq="D") | ||||
|         mask = notna(i2) | ||||
|  | ||||
|         result = pi.where(mask, i2.asi8) | ||||
|         expected = pd.Index([NaT._value, NaT._value] + tail, dtype=object) | ||||
|         assert isinstance(expected[0], int) | ||||
|         tm.assert_index_equal(result, expected) | ||||
|  | ||||
|         tdi = i2.asi8.view("timedelta64[ns]") | ||||
|         expected = pd.Index([tdi[0], tdi[1]] + tail, dtype=object) | ||||
|         assert isinstance(expected[0], np.timedelta64) | ||||
|         result = pi.where(mask, tdi) | ||||
|         tm.assert_index_equal(result, expected) | ||||
|  | ||||
|         dti = i2.to_timestamp("s") | ||||
|         expected = pd.Index([dti[0], dti[1]] + tail, dtype=object) | ||||
|         assert expected[0] is NaT | ||||
|         result = pi.where(mask, dti) | ||||
|         tm.assert_index_equal(result, expected) | ||||
|  | ||||
|         td = Timedelta(days=4) | ||||
|         expected = pd.Index([td, td] + tail, dtype=object) | ||||
|         assert expected[0] == td | ||||
|         result = pi.where(mask, td) | ||||
|         tm.assert_index_equal(result, expected) | ||||
|  | ||||
|     def test_where_mismatched_nat(self): | ||||
|         pi = period_range("20130101", periods=5, freq="D") | ||||
|         cond = np.array([True, False, True, True, False]) | ||||
|  | ||||
|         tdnat = np.timedelta64("NaT", "ns") | ||||
|         expected = pd.Index([pi[0], tdnat, pi[2], pi[3], tdnat], dtype=object) | ||||
|         assert expected[1] is tdnat | ||||
|         result = pi.where(cond, tdnat) | ||||
|         tm.assert_index_equal(result, expected) | ||||
|  | ||||
|  | ||||
| class TestTake: | ||||
|     def test_take(self): | ||||
|         # GH#10295 | ||||
|         idx1 = period_range("2011-01-01", "2011-01-31", freq="D", name="idx") | ||||
|  | ||||
|         for idx in [idx1]: | ||||
|             result = idx.take([0]) | ||||
|             assert result == Period("2011-01-01", freq="D") | ||||
|  | ||||
|             result = idx.take([5]) | ||||
|             assert result == Period("2011-01-06", freq="D") | ||||
|  | ||||
|             result = idx.take([0, 1, 2]) | ||||
|             expected = period_range("2011-01-01", "2011-01-03", freq="D", name="idx") | ||||
|             tm.assert_index_equal(result, expected) | ||||
|             assert result.freq == "D" | ||||
|             assert result.freq == expected.freq | ||||
|  | ||||
|             result = idx.take([0, 2, 4]) | ||||
|             expected = PeriodIndex( | ||||
|                 ["2011-01-01", "2011-01-03", "2011-01-05"], freq="D", name="idx" | ||||
|             ) | ||||
|             tm.assert_index_equal(result, expected) | ||||
|             assert result.freq == expected.freq | ||||
|             assert result.freq == "D" | ||||
|  | ||||
|             result = idx.take([7, 4, 1]) | ||||
|             expected = PeriodIndex( | ||||
|                 ["2011-01-08", "2011-01-05", "2011-01-02"], freq="D", name="idx" | ||||
|             ) | ||||
|             tm.assert_index_equal(result, expected) | ||||
|             assert result.freq == expected.freq | ||||
|             assert result.freq == "D" | ||||
|  | ||||
|             result = idx.take([3, 2, 5]) | ||||
|             expected = PeriodIndex( | ||||
|                 ["2011-01-04", "2011-01-03", "2011-01-06"], freq="D", name="idx" | ||||
|             ) | ||||
|             tm.assert_index_equal(result, expected) | ||||
|             assert result.freq == expected.freq | ||||
|             assert result.freq == "D" | ||||
|  | ||||
|             result = idx.take([-3, 2, 5]) | ||||
|             expected = PeriodIndex( | ||||
|                 ["2011-01-29", "2011-01-03", "2011-01-06"], freq="D", name="idx" | ||||
|             ) | ||||
|             tm.assert_index_equal(result, expected) | ||||
|             assert result.freq == expected.freq | ||||
|             assert result.freq == "D" | ||||
|  | ||||
|     def test_take_misc(self): | ||||
|         index = period_range(start="1/1/10", end="12/31/12", freq="D", name="idx") | ||||
|         expected = PeriodIndex( | ||||
|             [ | ||||
|                 datetime(2010, 1, 6), | ||||
|                 datetime(2010, 1, 7), | ||||
|                 datetime(2010, 1, 9), | ||||
|                 datetime(2010, 1, 13), | ||||
|             ], | ||||
|             freq="D", | ||||
|             name="idx", | ||||
|         ) | ||||
|  | ||||
|         taken1 = index.take([5, 6, 8, 12]) | ||||
|         taken2 = index[[5, 6, 8, 12]] | ||||
|  | ||||
|         for taken in [taken1, taken2]: | ||||
|             tm.assert_index_equal(taken, expected) | ||||
|             assert isinstance(taken, PeriodIndex) | ||||
|             assert taken.freq == index.freq | ||||
|             assert taken.name == expected.name | ||||
|  | ||||
|     def test_take_fill_value(self): | ||||
|         # GH#12631 | ||||
|         idx = PeriodIndex( | ||||
|             ["2011-01-01", "2011-02-01", "2011-03-01"], name="xxx", freq="D" | ||||
|         ) | ||||
|         result = idx.take(np.array([1, 0, -1])) | ||||
|         expected = PeriodIndex( | ||||
|             ["2011-02-01", "2011-01-01", "2011-03-01"], name="xxx", freq="D" | ||||
|         ) | ||||
|         tm.assert_index_equal(result, expected) | ||||
|  | ||||
|         # fill_value | ||||
|         result = idx.take(np.array([1, 0, -1]), fill_value=True) | ||||
|         expected = PeriodIndex( | ||||
|             ["2011-02-01", "2011-01-01", "NaT"], name="xxx", freq="D" | ||||
|         ) | ||||
|         tm.assert_index_equal(result, expected) | ||||
|  | ||||
|         # allow_fill=False | ||||
|         result = idx.take(np.array([1, 0, -1]), allow_fill=False, fill_value=True) | ||||
|         expected = PeriodIndex( | ||||
|             ["2011-02-01", "2011-01-01", "2011-03-01"], name="xxx", freq="D" | ||||
|         ) | ||||
|         tm.assert_index_equal(result, expected) | ||||
|  | ||||
|         msg = ( | ||||
|             "When allow_fill=True and fill_value is not None, " | ||||
|             "all indices must be >= -1" | ||||
|         ) | ||||
|         with pytest.raises(ValueError, match=msg): | ||||
|             idx.take(np.array([1, 0, -2]), fill_value=True) | ||||
|         with pytest.raises(ValueError, match=msg): | ||||
|             idx.take(np.array([1, 0, -5]), fill_value=True) | ||||
|  | ||||
|         msg = "index -5 is out of bounds for( axis 0 with)? size 3" | ||||
|         with pytest.raises(IndexError, match=msg): | ||||
|             idx.take(np.array([1, -5])) | ||||
|  | ||||
|  | ||||
| class TestGetValue: | ||||
|     @pytest.mark.parametrize("freq", ["h", "D"]) | ||||
|     def test_get_value_datetime_hourly(self, freq): | ||||
|         # get_loc and get_value should treat datetime objects symmetrically | ||||
|         # TODO: this test used to test get_value, which is removed in 2.0. | ||||
|         #  should this test be moved somewhere, or is what's left redundant? | ||||
|         dti = date_range("2016-01-01", periods=3, freq="MS") | ||||
|         pi = dti.to_period(freq) | ||||
|         ser = Series(range(7, 10), index=pi) | ||||
|  | ||||
|         ts = dti[0] | ||||
|  | ||||
|         assert pi.get_loc(ts) == 0 | ||||
|         assert ser[ts] == 7 | ||||
|         assert ser.loc[ts] == 7 | ||||
|  | ||||
|         ts2 = ts + Timedelta(hours=3) | ||||
|         if freq == "h": | ||||
|             with pytest.raises(KeyError, match="2016-01-01 03:00"): | ||||
|                 pi.get_loc(ts2) | ||||
|             with pytest.raises(KeyError, match="2016-01-01 03:00"): | ||||
|                 ser[ts2] | ||||
|             with pytest.raises(KeyError, match="2016-01-01 03:00"): | ||||
|                 ser.loc[ts2] | ||||
|         else: | ||||
|             assert pi.get_loc(ts2) == 0 | ||||
|             assert ser[ts2] == 7 | ||||
|             assert ser.loc[ts2] == 7 | ||||
|  | ||||
|  | ||||
| class TestContains: | ||||
|     def test_contains(self): | ||||
|         # GH 17717 | ||||
|         p0 = Period("2017-09-01") | ||||
|         p1 = Period("2017-09-02") | ||||
|         p2 = Period("2017-09-03") | ||||
|         p3 = Period("2017-09-04") | ||||
|  | ||||
|         ps0 = [p0, p1, p2] | ||||
|         idx0 = PeriodIndex(ps0) | ||||
|  | ||||
|         for p in ps0: | ||||
|             assert p in idx0 | ||||
|             assert str(p) in idx0 | ||||
|  | ||||
|         # GH#31172 | ||||
|         # Higher-resolution period-like are _not_ considered as contained | ||||
|         key = "2017-09-01 00:00:01" | ||||
|         assert key not in idx0 | ||||
|         with pytest.raises(KeyError, match=key): | ||||
|             idx0.get_loc(key) | ||||
|  | ||||
|         assert "2017-09" in idx0 | ||||
|  | ||||
|         assert p3 not in idx0 | ||||
|  | ||||
|     def test_contains_freq_mismatch(self): | ||||
|         rng = period_range("2007-01", freq="M", periods=10) | ||||
|  | ||||
|         assert Period("2007-01", freq="M") in rng | ||||
|         assert Period("2007-01", freq="D") not in rng | ||||
|         assert Period("2007-01", freq="2M") not in rng | ||||
|  | ||||
|     def test_contains_nat(self): | ||||
|         # see gh-13582 | ||||
|         idx = period_range("2007-01", freq="M", periods=10) | ||||
|         assert NaT not in idx | ||||
|         assert None not in idx | ||||
|         assert float("nan") not in idx | ||||
|         assert np.nan not in idx | ||||
|  | ||||
|         idx = PeriodIndex(["2011-01", "NaT", "2011-02"], freq="M") | ||||
|         assert NaT in idx | ||||
|         assert None in idx | ||||
|         assert float("nan") in idx | ||||
|         assert np.nan in idx | ||||
|  | ||||
|  | ||||
| class TestAsOfLocs: | ||||
|     def test_asof_locs_mismatched_type(self): | ||||
|         dti = date_range("2016-01-01", periods=3) | ||||
|         pi = dti.to_period("D") | ||||
|         pi2 = dti.to_period("h") | ||||
|  | ||||
|         mask = np.array([0, 1, 0], dtype=bool) | ||||
|  | ||||
|         msg = "must be DatetimeIndex or PeriodIndex" | ||||
|         with pytest.raises(TypeError, match=msg): | ||||
|             pi.asof_locs(pd.Index(pi.asi8, dtype=np.int64), mask) | ||||
|  | ||||
|         with pytest.raises(TypeError, match=msg): | ||||
|             pi.asof_locs(pd.Index(pi.asi8, dtype=np.float64), mask) | ||||
|  | ||||
|         with pytest.raises(TypeError, match=msg): | ||||
|             # TimedeltaIndex | ||||
|             pi.asof_locs(dti - dti, mask) | ||||
|  | ||||
|         msg = "Input has different freq=h" | ||||
|         with pytest.raises(libperiod.IncompatibleFrequency, match=msg): | ||||
|             pi.asof_locs(pi2, mask) | ||||
| @ -0,0 +1,58 @@ | ||||
| import numpy as np | ||||
| import pytest | ||||
|  | ||||
| from pandas._libs.tslibs import IncompatibleFrequency | ||||
|  | ||||
| from pandas import ( | ||||
|     DataFrame, | ||||
|     Index, | ||||
|     PeriodIndex, | ||||
|     date_range, | ||||
|     period_range, | ||||
| ) | ||||
| import pandas._testing as tm | ||||
|  | ||||
|  | ||||
| class TestJoin: | ||||
|     def test_join_outer_indexer(self): | ||||
|         pi = period_range("1/1/2000", "1/20/2000", freq="D") | ||||
|  | ||||
|         result = pi._outer_indexer(pi) | ||||
|         tm.assert_extension_array_equal(result[0], pi._values) | ||||
|         tm.assert_numpy_array_equal(result[1], np.arange(len(pi), dtype=np.intp)) | ||||
|         tm.assert_numpy_array_equal(result[2], np.arange(len(pi), dtype=np.intp)) | ||||
|  | ||||
|     def test_joins(self, join_type): | ||||
|         index = period_range("1/1/2000", "1/20/2000", freq="D") | ||||
|  | ||||
|         joined = index.join(index[:-5], how=join_type) | ||||
|  | ||||
|         assert isinstance(joined, PeriodIndex) | ||||
|         assert joined.freq == index.freq | ||||
|  | ||||
|     def test_join_self(self, join_type): | ||||
|         index = period_range("1/1/2000", "1/20/2000", freq="D") | ||||
|  | ||||
|         res = index.join(index, how=join_type) | ||||
|         assert index is res | ||||
|  | ||||
|     def test_join_does_not_recur(self): | ||||
|         df = DataFrame( | ||||
|             np.ones((3, 2)), | ||||
|             index=date_range("2020-01-01", periods=3), | ||||
|             columns=period_range("2020-01-01", periods=2), | ||||
|         ) | ||||
|         ser = df.iloc[:2, 0] | ||||
|  | ||||
|         res = ser.index.join(df.columns, how="outer") | ||||
|         expected = Index( | ||||
|             [ser.index[0], ser.index[1], df.columns[0], df.columns[1]], object | ||||
|         ) | ||||
|         tm.assert_index_equal(res, expected) | ||||
|  | ||||
|     def test_join_mismatched_freq_raises(self): | ||||
|         index = period_range("1/1/2000", "1/20/2000", freq="D") | ||||
|         index3 = period_range("1/1/2000", "1/20/2000", freq="2D") | ||||
|         msg = r".*Input has different freq=2D from Period\(freq=D\)" | ||||
|         with pytest.raises(IncompatibleFrequency, match=msg): | ||||
|             index.join(index3) | ||||
| @ -0,0 +1,42 @@ | ||||
| from pandas import ( | ||||
|     Period, | ||||
|     PeriodIndex, | ||||
| ) | ||||
|  | ||||
|  | ||||
| def test_is_monotonic_increasing(): | ||||
|     # GH#17717 | ||||
|     p0 = Period("2017-09-01") | ||||
|     p1 = Period("2017-09-02") | ||||
|     p2 = Period("2017-09-03") | ||||
|  | ||||
|     idx_inc0 = PeriodIndex([p0, p1, p2]) | ||||
|     idx_inc1 = PeriodIndex([p0, p1, p1]) | ||||
|     idx_dec0 = PeriodIndex([p2, p1, p0]) | ||||
|     idx_dec1 = PeriodIndex([p2, p1, p1]) | ||||
|     idx = PeriodIndex([p1, p2, p0]) | ||||
|  | ||||
|     assert idx_inc0.is_monotonic_increasing is True | ||||
|     assert idx_inc1.is_monotonic_increasing is True | ||||
|     assert idx_dec0.is_monotonic_increasing is False | ||||
|     assert idx_dec1.is_monotonic_increasing is False | ||||
|     assert idx.is_monotonic_increasing is False | ||||
|  | ||||
|  | ||||
| def test_is_monotonic_decreasing(): | ||||
|     # GH#17717 | ||||
|     p0 = Period("2017-09-01") | ||||
|     p1 = Period("2017-09-02") | ||||
|     p2 = Period("2017-09-03") | ||||
|  | ||||
|     idx_inc0 = PeriodIndex([p0, p1, p2]) | ||||
|     idx_inc1 = PeriodIndex([p0, p1, p1]) | ||||
|     idx_dec0 = PeriodIndex([p2, p1, p0]) | ||||
|     idx_dec1 = PeriodIndex([p2, p1, p1]) | ||||
|     idx = PeriodIndex([p1, p2, p0]) | ||||
|  | ||||
|     assert idx_inc0.is_monotonic_decreasing is False | ||||
|     assert idx_inc1.is_monotonic_decreasing is False | ||||
|     assert idx_dec0.is_monotonic_decreasing is True | ||||
|     assert idx_dec1.is_monotonic_decreasing is True | ||||
|     assert idx.is_monotonic_decreasing is False | ||||
| @ -0,0 +1,198 @@ | ||||
| import numpy as np | ||||
| import pytest | ||||
|  | ||||
| from pandas import ( | ||||
|     DataFrame, | ||||
|     PeriodIndex, | ||||
|     Series, | ||||
|     date_range, | ||||
|     period_range, | ||||
| ) | ||||
| import pandas._testing as tm | ||||
|  | ||||
|  | ||||
| class TestPeriodIndex: | ||||
|     def test_getitem_periodindex_duplicates_string_slice( | ||||
|         self, using_copy_on_write, warn_copy_on_write | ||||
|     ): | ||||
|         # monotonic | ||||
|         idx = PeriodIndex([2000, 2007, 2007, 2009, 2009], freq="Y-JUN") | ||||
|         ts = Series(np.random.default_rng(2).standard_normal(len(idx)), index=idx) | ||||
|         original = ts.copy() | ||||
|  | ||||
|         result = ts["2007"] | ||||
|         expected = ts[1:3] | ||||
|         tm.assert_series_equal(result, expected) | ||||
|         with tm.assert_cow_warning(warn_copy_on_write): | ||||
|             result[:] = 1 | ||||
|         if using_copy_on_write: | ||||
|             tm.assert_series_equal(ts, original) | ||||
|         else: | ||||
|             assert (ts[1:3] == 1).all() | ||||
|  | ||||
|         # not monotonic | ||||
|         idx = PeriodIndex([2000, 2007, 2007, 2009, 2007], freq="Y-JUN") | ||||
|         ts = Series(np.random.default_rng(2).standard_normal(len(idx)), index=idx) | ||||
|  | ||||
|         result = ts["2007"] | ||||
|         expected = ts[idx == "2007"] | ||||
|         tm.assert_series_equal(result, expected) | ||||
|  | ||||
|     def test_getitem_periodindex_quarter_string(self): | ||||
|         pi = PeriodIndex(["2Q05", "3Q05", "4Q05", "1Q06", "2Q06"], freq="Q") | ||||
|         ser = Series(np.random.default_rng(2).random(len(pi)), index=pi).cumsum() | ||||
|         # Todo: fix these accessors! | ||||
|         assert ser["05Q4"] == ser.iloc[2] | ||||
|  | ||||
|     def test_pindex_slice_index(self): | ||||
|         pi = period_range(start="1/1/10", end="12/31/12", freq="M") | ||||
|         s = Series(np.random.default_rng(2).random(len(pi)), index=pi) | ||||
|         res = s["2010"] | ||||
|         exp = s[0:12] | ||||
|         tm.assert_series_equal(res, exp) | ||||
|         res = s["2011"] | ||||
|         exp = s[12:24] | ||||
|         tm.assert_series_equal(res, exp) | ||||
|  | ||||
|     @pytest.mark.parametrize("make_range", [date_range, period_range]) | ||||
|     def test_range_slice_day(self, make_range): | ||||
|         # GH#6716 | ||||
|         idx = make_range(start="2013/01/01", freq="D", periods=400) | ||||
|  | ||||
|         msg = "slice indices must be integers or None or have an __index__ method" | ||||
|         # slices against index should raise IndexError | ||||
|         values = [ | ||||
|             "2014", | ||||
|             "2013/02", | ||||
|             "2013/01/02", | ||||
|             "2013/02/01 9H", | ||||
|             "2013/02/01 09:00", | ||||
|         ] | ||||
|         for v in values: | ||||
|             with pytest.raises(TypeError, match=msg): | ||||
|                 idx[v:] | ||||
|  | ||||
|         s = Series(np.random.default_rng(2).random(len(idx)), index=idx) | ||||
|  | ||||
|         tm.assert_series_equal(s["2013/01/02":], s[1:]) | ||||
|         tm.assert_series_equal(s["2013/01/02":"2013/01/05"], s[1:5]) | ||||
|         tm.assert_series_equal(s["2013/02":], s[31:]) | ||||
|         tm.assert_series_equal(s["2014":], s[365:]) | ||||
|  | ||||
|         invalid = ["2013/02/01 9H", "2013/02/01 09:00"] | ||||
|         for v in invalid: | ||||
|             with pytest.raises(TypeError, match=msg): | ||||
|                 idx[v:] | ||||
|  | ||||
|     @pytest.mark.parametrize("make_range", [date_range, period_range]) | ||||
|     def test_range_slice_seconds(self, make_range): | ||||
|         # GH#6716 | ||||
|         idx = make_range(start="2013/01/01 09:00:00", freq="s", periods=4000) | ||||
|         msg = "slice indices must be integers or None or have an __index__ method" | ||||
|  | ||||
|         # slices against index should raise IndexError | ||||
|         values = [ | ||||
|             "2014", | ||||
|             "2013/02", | ||||
|             "2013/01/02", | ||||
|             "2013/02/01 9H", | ||||
|             "2013/02/01 09:00", | ||||
|         ] | ||||
|         for v in values: | ||||
|             with pytest.raises(TypeError, match=msg): | ||||
|                 idx[v:] | ||||
|  | ||||
|         s = Series(np.random.default_rng(2).random(len(idx)), index=idx) | ||||
|  | ||||
|         tm.assert_series_equal(s["2013/01/01 09:05":"2013/01/01 09:10"], s[300:660]) | ||||
|         tm.assert_series_equal(s["2013/01/01 10:00":"2013/01/01 10:05"], s[3600:3960]) | ||||
|         tm.assert_series_equal(s["2013/01/01 10H":], s[3600:]) | ||||
|         tm.assert_series_equal(s[:"2013/01/01 09:30"], s[:1860]) | ||||
|         for d in ["2013/01/01", "2013/01", "2013"]: | ||||
|             tm.assert_series_equal(s[d:], s) | ||||
|  | ||||
|     @pytest.mark.parametrize("make_range", [date_range, period_range]) | ||||
|     def test_range_slice_outofbounds(self, make_range): | ||||
|         # GH#5407 | ||||
|         idx = make_range(start="2013/10/01", freq="D", periods=10) | ||||
|  | ||||
|         df = DataFrame({"units": [100 + i for i in range(10)]}, index=idx) | ||||
|         empty = DataFrame(index=idx[:0], columns=["units"]) | ||||
|         empty["units"] = empty["units"].astype("int64") | ||||
|  | ||||
|         tm.assert_frame_equal(df["2013/09/01":"2013/09/30"], empty) | ||||
|         tm.assert_frame_equal(df["2013/09/30":"2013/10/02"], df.iloc[:2]) | ||||
|         tm.assert_frame_equal(df["2013/10/01":"2013/10/02"], df.iloc[:2]) | ||||
|         tm.assert_frame_equal(df["2013/10/02":"2013/09/30"], empty) | ||||
|         tm.assert_frame_equal(df["2013/10/15":"2013/10/17"], empty) | ||||
|         tm.assert_frame_equal(df["2013-06":"2013-09"], empty) | ||||
|         tm.assert_frame_equal(df["2013-11":"2013-12"], empty) | ||||
|  | ||||
|     @pytest.mark.parametrize("make_range", [date_range, period_range]) | ||||
|     def test_maybe_cast_slice_bound(self, make_range, frame_or_series): | ||||
|         idx = make_range(start="2013/10/01", freq="D", periods=10) | ||||
|  | ||||
|         obj = DataFrame({"units": [100 + i for i in range(10)]}, index=idx) | ||||
|         obj = tm.get_obj(obj, frame_or_series) | ||||
|  | ||||
|         msg = ( | ||||
|             f"cannot do slice indexing on {type(idx).__name__} with " | ||||
|             r"these indexers \[foo\] of type str" | ||||
|         ) | ||||
|  | ||||
|         # Check the lower-level calls are raising where expected. | ||||
|         with pytest.raises(TypeError, match=msg): | ||||
|             idx._maybe_cast_slice_bound("foo", "left") | ||||
|         with pytest.raises(TypeError, match=msg): | ||||
|             idx.get_slice_bound("foo", "left") | ||||
|  | ||||
|         with pytest.raises(TypeError, match=msg): | ||||
|             obj["2013/09/30":"foo"] | ||||
|         with pytest.raises(TypeError, match=msg): | ||||
|             obj["foo":"2013/09/30"] | ||||
|         with pytest.raises(TypeError, match=msg): | ||||
|             obj.loc["2013/09/30":"foo"] | ||||
|         with pytest.raises(TypeError, match=msg): | ||||
|             obj.loc["foo":"2013/09/30"] | ||||
|  | ||||
|     def test_partial_slice_doesnt_require_monotonicity(self): | ||||
|         # See also: DatetimeIndex test ofm the same name | ||||
|         dti = date_range("2014-01-01", periods=30, freq="30D") | ||||
|         pi = dti.to_period("D") | ||||
|  | ||||
|         ser_montonic = Series(np.arange(30), index=pi) | ||||
|  | ||||
|         shuffler = list(range(0, 30, 2)) + list(range(1, 31, 2)) | ||||
|         ser = ser_montonic.iloc[shuffler] | ||||
|         nidx = ser.index | ||||
|  | ||||
|         # Manually identified locations of year==2014 | ||||
|         indexer_2014 = np.array( | ||||
|             [0, 1, 2, 3, 4, 5, 6, 15, 16, 17, 18, 19, 20], dtype=np.intp | ||||
|         ) | ||||
|         assert (nidx[indexer_2014].year == 2014).all() | ||||
|         assert not (nidx[~indexer_2014].year == 2014).any() | ||||
|  | ||||
|         result = nidx.get_loc("2014") | ||||
|         tm.assert_numpy_array_equal(result, indexer_2014) | ||||
|  | ||||
|         expected = ser.iloc[indexer_2014] | ||||
|         result = ser.loc["2014"] | ||||
|         tm.assert_series_equal(result, expected) | ||||
|  | ||||
|         result = ser["2014"] | ||||
|         tm.assert_series_equal(result, expected) | ||||
|  | ||||
|         # Manually identified locations where ser.index is within Mat 2015 | ||||
|         indexer_may2015 = np.array([23], dtype=np.intp) | ||||
|         assert nidx[23].year == 2015 and nidx[23].month == 5 | ||||
|  | ||||
|         result = nidx.get_loc("May 2015") | ||||
|         tm.assert_numpy_array_equal(result, indexer_may2015) | ||||
|  | ||||
|         expected = ser.iloc[indexer_may2015] | ||||
|         result = ser.loc["May 2015"] | ||||
|         tm.assert_series_equal(result, expected) | ||||
|  | ||||
|         result = ser["May 2015"] | ||||
|         tm.assert_series_equal(result, expected) | ||||
| @ -0,0 +1,231 @@ | ||||
| import numpy as np | ||||
| import pytest | ||||
|  | ||||
| from pandas import ( | ||||
|     Index, | ||||
|     NaT, | ||||
|     Period, | ||||
|     PeriodIndex, | ||||
|     Series, | ||||
|     date_range, | ||||
|     offsets, | ||||
|     period_range, | ||||
| ) | ||||
| import pandas._testing as tm | ||||
|  | ||||
|  | ||||
| class TestPeriodIndex: | ||||
|     def test_view_asi8(self): | ||||
|         idx = PeriodIndex([], freq="M") | ||||
|  | ||||
|         exp = np.array([], dtype=np.int64) | ||||
|         tm.assert_numpy_array_equal(idx.view("i8"), exp) | ||||
|         tm.assert_numpy_array_equal(idx.asi8, exp) | ||||
|  | ||||
|         idx = PeriodIndex(["2011-01", NaT], freq="M") | ||||
|  | ||||
|         exp = np.array([492, -9223372036854775808], dtype=np.int64) | ||||
|         tm.assert_numpy_array_equal(idx.view("i8"), exp) | ||||
|         tm.assert_numpy_array_equal(idx.asi8, exp) | ||||
|  | ||||
|         exp = np.array([14975, -9223372036854775808], dtype=np.int64) | ||||
|         idx = PeriodIndex(["2011-01-01", NaT], freq="D") | ||||
|         tm.assert_numpy_array_equal(idx.view("i8"), exp) | ||||
|         tm.assert_numpy_array_equal(idx.asi8, exp) | ||||
|  | ||||
|     def test_values(self): | ||||
|         idx = PeriodIndex([], freq="M") | ||||
|  | ||||
|         exp = np.array([], dtype=object) | ||||
|         tm.assert_numpy_array_equal(idx.values, exp) | ||||
|         tm.assert_numpy_array_equal(idx.to_numpy(), exp) | ||||
|  | ||||
|         exp = np.array([], dtype=np.int64) | ||||
|         tm.assert_numpy_array_equal(idx.asi8, exp) | ||||
|  | ||||
|         idx = PeriodIndex(["2011-01", NaT], freq="M") | ||||
|  | ||||
|         exp = np.array([Period("2011-01", freq="M"), NaT], dtype=object) | ||||
|         tm.assert_numpy_array_equal(idx.values, exp) | ||||
|         tm.assert_numpy_array_equal(idx.to_numpy(), exp) | ||||
|         exp = np.array([492, -9223372036854775808], dtype=np.int64) | ||||
|         tm.assert_numpy_array_equal(idx.asi8, exp) | ||||
|  | ||||
|         idx = PeriodIndex(["2011-01-01", NaT], freq="D") | ||||
|  | ||||
|         exp = np.array([Period("2011-01-01", freq="D"), NaT], dtype=object) | ||||
|         tm.assert_numpy_array_equal(idx.values, exp) | ||||
|         tm.assert_numpy_array_equal(idx.to_numpy(), exp) | ||||
|         exp = np.array([14975, -9223372036854775808], dtype=np.int64) | ||||
|         tm.assert_numpy_array_equal(idx.asi8, exp) | ||||
|  | ||||
|     @pytest.mark.parametrize( | ||||
|         "field", | ||||
|         [ | ||||
|             "year", | ||||
|             "month", | ||||
|             "day", | ||||
|             "hour", | ||||
|             "minute", | ||||
|             "second", | ||||
|             "weekofyear", | ||||
|             "week", | ||||
|             "dayofweek", | ||||
|             "day_of_week", | ||||
|             "dayofyear", | ||||
|             "day_of_year", | ||||
|             "quarter", | ||||
|             "qyear", | ||||
|             "days_in_month", | ||||
|         ], | ||||
|     ) | ||||
|     @pytest.mark.parametrize( | ||||
|         "periodindex", | ||||
|         [ | ||||
|             period_range(freq="Y", start="1/1/2001", end="12/1/2005"), | ||||
|             period_range(freq="Q", start="1/1/2001", end="12/1/2002"), | ||||
|             period_range(freq="M", start="1/1/2001", end="1/1/2002"), | ||||
|             period_range(freq="D", start="12/1/2001", end="6/1/2001"), | ||||
|             period_range(freq="h", start="12/31/2001", end="1/1/2002 23:00"), | ||||
|             period_range(freq="Min", start="12/31/2001", end="1/1/2002 00:20"), | ||||
|             period_range( | ||||
|                 freq="s", start="12/31/2001 00:00:00", end="12/31/2001 00:05:00" | ||||
|             ), | ||||
|             period_range(end=Period("2006-12-31", "W"), periods=10), | ||||
|         ], | ||||
|     ) | ||||
|     def test_fields(self, periodindex, field): | ||||
|         periods = list(periodindex) | ||||
|         ser = Series(periodindex) | ||||
|  | ||||
|         field_idx = getattr(periodindex, field) | ||||
|         assert len(periodindex) == len(field_idx) | ||||
|         for x, val in zip(periods, field_idx): | ||||
|             assert getattr(x, field) == val | ||||
|  | ||||
|         if len(ser) == 0: | ||||
|             return | ||||
|  | ||||
|         field_s = getattr(ser.dt, field) | ||||
|         assert len(periodindex) == len(field_s) | ||||
|         for x, val in zip(periods, field_s): | ||||
|             assert getattr(x, field) == val | ||||
|  | ||||
|     def test_is_(self): | ||||
|         create_index = lambda: period_range(freq="Y", start="1/1/2001", end="12/1/2009") | ||||
|         index = create_index() | ||||
|         assert index.is_(index) | ||||
|         assert not index.is_(create_index()) | ||||
|         assert index.is_(index.view()) | ||||
|         assert index.is_(index.view().view().view().view().view()) | ||||
|         assert index.view().is_(index) | ||||
|         ind2 = index.view() | ||||
|         index.name = "Apple" | ||||
|         assert ind2.is_(index) | ||||
|         assert not index.is_(index[:]) | ||||
|         assert not index.is_(index.asfreq("M")) | ||||
|         assert not index.is_(index.asfreq("Y")) | ||||
|  | ||||
|         assert not index.is_(index - 2) | ||||
|         assert not index.is_(index - 0) | ||||
|  | ||||
|     def test_index_unique(self): | ||||
|         idx = PeriodIndex([2000, 2007, 2007, 2009, 2009], freq="Y-JUN") | ||||
|         expected = PeriodIndex([2000, 2007, 2009], freq="Y-JUN") | ||||
|         tm.assert_index_equal(idx.unique(), expected) | ||||
|         assert idx.nunique() == 3 | ||||
|  | ||||
|     def test_pindex_fieldaccessor_nat(self): | ||||
|         idx = PeriodIndex( | ||||
|             ["2011-01", "2011-02", "NaT", "2012-03", "2012-04"], freq="D", name="name" | ||||
|         ) | ||||
|  | ||||
|         exp = Index([2011, 2011, -1, 2012, 2012], dtype=np.int64, name="name") | ||||
|         tm.assert_index_equal(idx.year, exp) | ||||
|         exp = Index([1, 2, -1, 3, 4], dtype=np.int64, name="name") | ||||
|         tm.assert_index_equal(idx.month, exp) | ||||
|  | ||||
|     def test_pindex_multiples(self): | ||||
|         expected = PeriodIndex( | ||||
|             ["2011-01", "2011-03", "2011-05", "2011-07", "2011-09", "2011-11"], | ||||
|             freq="2M", | ||||
|         ) | ||||
|  | ||||
|         pi = period_range(start="1/1/11", end="12/31/11", freq="2M") | ||||
|         tm.assert_index_equal(pi, expected) | ||||
|         assert pi.freq == offsets.MonthEnd(2) | ||||
|         assert pi.freqstr == "2M" | ||||
|  | ||||
|         pi = period_range(start="1/1/11", periods=6, freq="2M") | ||||
|         tm.assert_index_equal(pi, expected) | ||||
|         assert pi.freq == offsets.MonthEnd(2) | ||||
|         assert pi.freqstr == "2M" | ||||
|  | ||||
|     @pytest.mark.filterwarnings(r"ignore:PeriodDtype\[B\] is deprecated:FutureWarning") | ||||
|     @pytest.mark.filterwarnings("ignore:Period with BDay freq:FutureWarning") | ||||
|     def test_iteration(self): | ||||
|         index = period_range(start="1/1/10", periods=4, freq="B") | ||||
|  | ||||
|         result = list(index) | ||||
|         assert isinstance(result[0], Period) | ||||
|         assert result[0].freq == index.freq | ||||
|  | ||||
|     def test_with_multi_index(self): | ||||
|         # #1705 | ||||
|         index = date_range("1/1/2012", periods=4, freq="12h") | ||||
|         index_as_arrays = [index.to_period(freq="D"), index.hour] | ||||
|  | ||||
|         s = Series([0, 1, 2, 3], index_as_arrays) | ||||
|  | ||||
|         assert isinstance(s.index.levels[0], PeriodIndex) | ||||
|  | ||||
|         assert isinstance(s.index.values[0][0], Period) | ||||
|  | ||||
|     def test_map(self): | ||||
|         # test_map_dictlike generally tests | ||||
|  | ||||
|         index = PeriodIndex([2005, 2007, 2009], freq="Y") | ||||
|         result = index.map(lambda x: x.ordinal) | ||||
|         exp = Index([x.ordinal for x in index]) | ||||
|         tm.assert_index_equal(result, exp) | ||||
|  | ||||
|  | ||||
| def test_maybe_convert_timedelta(): | ||||
|     pi = PeriodIndex(["2000", "2001"], freq="D") | ||||
|     offset = offsets.Day(2) | ||||
|     assert pi._maybe_convert_timedelta(offset) == 2 | ||||
|     assert pi._maybe_convert_timedelta(2) == 2 | ||||
|  | ||||
|     offset = offsets.BusinessDay() | ||||
|     msg = r"Input has different freq=B from PeriodIndex\(freq=D\)" | ||||
|     with pytest.raises(ValueError, match=msg): | ||||
|         pi._maybe_convert_timedelta(offset) | ||||
|  | ||||
|  | ||||
| @pytest.mark.parametrize("array", [True, False]) | ||||
| def test_dunder_array(array): | ||||
|     obj = PeriodIndex(["2000-01-01", "2001-01-01"], freq="D") | ||||
|     if array: | ||||
|         obj = obj._data | ||||
|  | ||||
|     expected = np.array([obj[0], obj[1]], dtype=object) | ||||
|     result = np.array(obj) | ||||
|     tm.assert_numpy_array_equal(result, expected) | ||||
|  | ||||
|     result = np.asarray(obj) | ||||
|     tm.assert_numpy_array_equal(result, expected) | ||||
|  | ||||
|     expected = obj.asi8 | ||||
|     for dtype in ["i8", "int64", np.int64]: | ||||
|         result = np.array(obj, dtype=dtype) | ||||
|         tm.assert_numpy_array_equal(result, expected) | ||||
|  | ||||
|         result = np.asarray(obj, dtype=dtype) | ||||
|         tm.assert_numpy_array_equal(result, expected) | ||||
|  | ||||
|     for dtype in ["float64", "int32", "uint64"]: | ||||
|         msg = "argument must be" | ||||
|         with pytest.raises(TypeError, match=msg): | ||||
|             np.array(obj, dtype=dtype) | ||||
|         with pytest.raises(TypeError, match=msg): | ||||
|             np.array(obj, dtype=getattr(np, dtype)) | ||||
| @ -0,0 +1,241 @@ | ||||
| import numpy as np | ||||
| import pytest | ||||
|  | ||||
| from pandas import ( | ||||
|     NaT, | ||||
|     Period, | ||||
|     PeriodIndex, | ||||
|     date_range, | ||||
|     period_range, | ||||
| ) | ||||
| import pandas._testing as tm | ||||
|  | ||||
|  | ||||
| class TestPeriodRangeKeywords: | ||||
|     def test_required_arguments(self): | ||||
|         msg = ( | ||||
|             "Of the three parameters: start, end, and periods, exactly two " | ||||
|             "must be specified" | ||||
|         ) | ||||
|         with pytest.raises(ValueError, match=msg): | ||||
|             period_range("2011-1-1", "2012-1-1", "B") | ||||
|  | ||||
|     def test_required_arguments2(self): | ||||
|         start = Period("02-Apr-2005", "D") | ||||
|         msg = ( | ||||
|             "Of the three parameters: start, end, and periods, exactly two " | ||||
|             "must be specified" | ||||
|         ) | ||||
|         with pytest.raises(ValueError, match=msg): | ||||
|             period_range(start=start) | ||||
|  | ||||
|     def test_required_arguments3(self): | ||||
|         # not enough params | ||||
|         msg = ( | ||||
|             "Of the three parameters: start, end, and periods, " | ||||
|             "exactly two must be specified" | ||||
|         ) | ||||
|         with pytest.raises(ValueError, match=msg): | ||||
|             period_range(start="2017Q1") | ||||
|  | ||||
|         with pytest.raises(ValueError, match=msg): | ||||
|             period_range(end="2017Q1") | ||||
|  | ||||
|         with pytest.raises(ValueError, match=msg): | ||||
|             period_range(periods=5) | ||||
|  | ||||
|         with pytest.raises(ValueError, match=msg): | ||||
|             period_range() | ||||
|  | ||||
|     def test_required_arguments_too_many(self): | ||||
|         msg = ( | ||||
|             "Of the three parameters: start, end, and periods, " | ||||
|             "exactly two must be specified" | ||||
|         ) | ||||
|         with pytest.raises(ValueError, match=msg): | ||||
|             period_range(start="2017Q1", end="2018Q1", periods=8, freq="Q") | ||||
|  | ||||
|     def test_start_end_non_nat(self): | ||||
|         # start/end NaT | ||||
|         msg = "start and end must not be NaT" | ||||
|         with pytest.raises(ValueError, match=msg): | ||||
|             period_range(start=NaT, end="2018Q1") | ||||
|         with pytest.raises(ValueError, match=msg): | ||||
|             period_range(start=NaT, end="2018Q1", freq="Q") | ||||
|  | ||||
|         with pytest.raises(ValueError, match=msg): | ||||
|             period_range(start="2017Q1", end=NaT) | ||||
|         with pytest.raises(ValueError, match=msg): | ||||
|             period_range(start="2017Q1", end=NaT, freq="Q") | ||||
|  | ||||
|     def test_periods_requires_integer(self): | ||||
|         # invalid periods param | ||||
|         msg = "periods must be a number, got foo" | ||||
|         with pytest.raises(TypeError, match=msg): | ||||
|             period_range(start="2017Q1", periods="foo") | ||||
|  | ||||
|  | ||||
| class TestPeriodRange: | ||||
|     @pytest.mark.parametrize( | ||||
|         "freq_offset, freq_period", | ||||
|         [ | ||||
|             ("D", "D"), | ||||
|             ("W", "W"), | ||||
|             ("QE", "Q"), | ||||
|             ("YE", "Y"), | ||||
|         ], | ||||
|     ) | ||||
|     def test_construction_from_string(self, freq_offset, freq_period): | ||||
|         # non-empty | ||||
|         expected = date_range( | ||||
|             start="2017-01-01", periods=5, freq=freq_offset, name="foo" | ||||
|         ).to_period() | ||||
|         start, end = str(expected[0]), str(expected[-1]) | ||||
|  | ||||
|         result = period_range(start=start, end=end, freq=freq_period, name="foo") | ||||
|         tm.assert_index_equal(result, expected) | ||||
|  | ||||
|         result = period_range(start=start, periods=5, freq=freq_period, name="foo") | ||||
|         tm.assert_index_equal(result, expected) | ||||
|  | ||||
|         result = period_range(end=end, periods=5, freq=freq_period, name="foo") | ||||
|         tm.assert_index_equal(result, expected) | ||||
|  | ||||
|         # empty | ||||
|         expected = PeriodIndex([], freq=freq_period, name="foo") | ||||
|  | ||||
|         result = period_range(start=start, periods=0, freq=freq_period, name="foo") | ||||
|         tm.assert_index_equal(result, expected) | ||||
|  | ||||
|         result = period_range(end=end, periods=0, freq=freq_period, name="foo") | ||||
|         tm.assert_index_equal(result, expected) | ||||
|  | ||||
|         result = period_range(start=end, end=start, freq=freq_period, name="foo") | ||||
|         tm.assert_index_equal(result, expected) | ||||
|  | ||||
|     def test_construction_from_string_monthly(self): | ||||
|         # non-empty | ||||
|         expected = date_range( | ||||
|             start="2017-01-01", periods=5, freq="ME", name="foo" | ||||
|         ).to_period() | ||||
|         start, end = str(expected[0]), str(expected[-1]) | ||||
|  | ||||
|         result = period_range(start=start, end=end, freq="M", name="foo") | ||||
|         tm.assert_index_equal(result, expected) | ||||
|  | ||||
|         result = period_range(start=start, periods=5, freq="M", name="foo") | ||||
|         tm.assert_index_equal(result, expected) | ||||
|  | ||||
|         result = period_range(end=end, periods=5, freq="M", name="foo") | ||||
|         tm.assert_index_equal(result, expected) | ||||
|  | ||||
|         # empty | ||||
|         expected = PeriodIndex([], freq="M", name="foo") | ||||
|  | ||||
|         result = period_range(start=start, periods=0, freq="M", name="foo") | ||||
|         tm.assert_index_equal(result, expected) | ||||
|  | ||||
|         result = period_range(end=end, periods=0, freq="M", name="foo") | ||||
|         tm.assert_index_equal(result, expected) | ||||
|  | ||||
|         result = period_range(start=end, end=start, freq="M", name="foo") | ||||
|         tm.assert_index_equal(result, expected) | ||||
|  | ||||
|     def test_construction_from_period(self): | ||||
|         # upsampling | ||||
|         start, end = Period("2017Q1", freq="Q"), Period("2018Q1", freq="Q") | ||||
|         expected = date_range( | ||||
|             start="2017-03-31", end="2018-03-31", freq="ME", name="foo" | ||||
|         ).to_period() | ||||
|         result = period_range(start=start, end=end, freq="M", name="foo") | ||||
|         tm.assert_index_equal(result, expected) | ||||
|  | ||||
|         # downsampling | ||||
|         start = Period("2017-1", freq="M") | ||||
|         end = Period("2019-12", freq="M") | ||||
|         expected = date_range( | ||||
|             start="2017-01-31", end="2019-12-31", freq="QE", name="foo" | ||||
|         ).to_period() | ||||
|         result = period_range(start=start, end=end, freq="Q", name="foo") | ||||
|         tm.assert_index_equal(result, expected) | ||||
|  | ||||
|         # test for issue # 21793 | ||||
|         start = Period("2017Q1", freq="Q") | ||||
|         end = Period("2018Q1", freq="Q") | ||||
|         idx = period_range(start=start, end=end, freq="Q", name="foo") | ||||
|         result = idx == idx.values | ||||
|         expected = np.array([True, True, True, True, True]) | ||||
|         tm.assert_numpy_array_equal(result, expected) | ||||
|  | ||||
|         # empty | ||||
|         expected = PeriodIndex([], freq="W", name="foo") | ||||
|  | ||||
|         result = period_range(start=start, periods=0, freq="W", name="foo") | ||||
|         tm.assert_index_equal(result, expected) | ||||
|  | ||||
|         result = period_range(end=end, periods=0, freq="W", name="foo") | ||||
|         tm.assert_index_equal(result, expected) | ||||
|  | ||||
|         result = period_range(start=end, end=start, freq="W", name="foo") | ||||
|         tm.assert_index_equal(result, expected) | ||||
|  | ||||
|     def test_mismatched_start_end_freq_raises(self): | ||||
|         depr_msg = "Period with BDay freq is deprecated" | ||||
|         msg = "'w' is deprecated and will be removed in a future version." | ||||
|         with tm.assert_produces_warning(FutureWarning, match=msg): | ||||
|             end_w = Period("2006-12-31", "1w") | ||||
|  | ||||
|         with tm.assert_produces_warning(FutureWarning, match=depr_msg): | ||||
|             start_b = Period("02-Apr-2005", "B") | ||||
|             end_b = Period("2005-05-01", "B") | ||||
|  | ||||
|         msg = "start and end must have same freq" | ||||
|         with pytest.raises(ValueError, match=msg): | ||||
|             with tm.assert_produces_warning(FutureWarning, match=depr_msg): | ||||
|                 period_range(start=start_b, end=end_w) | ||||
|  | ||||
|         # without mismatch we are OK | ||||
|         with tm.assert_produces_warning(FutureWarning, match=depr_msg): | ||||
|             period_range(start=start_b, end=end_b) | ||||
|  | ||||
|  | ||||
| class TestPeriodRangeDisallowedFreqs: | ||||
|     def test_constructor_U(self): | ||||
|         # U was used as undefined period | ||||
|         with pytest.raises(ValueError, match="Invalid frequency: X"): | ||||
|             period_range("2007-1-1", periods=500, freq="X") | ||||
|  | ||||
|     @pytest.mark.parametrize( | ||||
|         "freq,freq_depr", | ||||
|         [ | ||||
|             ("2Y", "2A"), | ||||
|             ("2Y", "2a"), | ||||
|             ("2Y-AUG", "2A-AUG"), | ||||
|             ("2Y-AUG", "2A-aug"), | ||||
|         ], | ||||
|     ) | ||||
|     def test_a_deprecated_from_time_series(self, freq, freq_depr): | ||||
|         # GH#52536 | ||||
|         msg = f"'{freq_depr[1:]}' is deprecated and will be removed in a " | ||||
|         f"future version. Please use '{freq[1:]}' instead." | ||||
|  | ||||
|         with tm.assert_produces_warning(FutureWarning, match=msg): | ||||
|             period_range(freq=freq_depr, start="1/1/2001", end="12/1/2009") | ||||
|  | ||||
|     @pytest.mark.parametrize("freq_depr", ["2H", "2MIN", "2S", "2US", "2NS"]) | ||||
|     def test_uppercase_freq_deprecated_from_time_series(self, freq_depr): | ||||
|         # GH#52536, GH#54939 | ||||
|         msg = f"'{freq_depr[1:]}' is deprecated and will be removed in a " | ||||
|         f"future version. Please use '{freq_depr.lower()[1:]}' instead." | ||||
|  | ||||
|         with tm.assert_produces_warning(FutureWarning, match=msg): | ||||
|             period_range("2020-01-01 00:00:00 00:00", periods=2, freq=freq_depr) | ||||
|  | ||||
|     @pytest.mark.parametrize("freq_depr", ["2m", "2q-sep", "2y", "2w"]) | ||||
|     def test_lowercase_freq_deprecated_from_time_series(self, freq_depr): | ||||
|         # GH#52536, GH#54939 | ||||
|         msg = f"'{freq_depr[1:]}' is deprecated and will be removed in a " | ||||
|         f"future version. Please use '{freq_depr.upper()[1:]}' instead." | ||||
|  | ||||
|         with tm.assert_produces_warning(FutureWarning, match=msg): | ||||
|             period_range(freq=freq_depr, start="1/1/2001", end="12/1/2009") | ||||
| @ -0,0 +1,26 @@ | ||||
| import numpy as np | ||||
| import pytest | ||||
|  | ||||
| from pandas import ( | ||||
|     NaT, | ||||
|     PeriodIndex, | ||||
|     period_range, | ||||
| ) | ||||
| import pandas._testing as tm | ||||
|  | ||||
| from pandas.tseries import offsets | ||||
|  | ||||
|  | ||||
| class TestPickle: | ||||
|     @pytest.mark.parametrize("freq", ["D", "M", "Y"]) | ||||
|     def test_pickle_round_trip(self, freq): | ||||
|         idx = PeriodIndex(["2016-05-16", "NaT", NaT, np.nan], freq=freq) | ||||
|         result = tm.round_trip_pickle(idx) | ||||
|         tm.assert_index_equal(result, idx) | ||||
|  | ||||
|     def test_pickle_freq(self): | ||||
|         # GH#2891 | ||||
|         prng = period_range("1/1/2011", "1/1/2012", freq="M") | ||||
|         new_prng = tm.round_trip_pickle(prng) | ||||
|         assert new_prng.freq == offsets.MonthEnd() | ||||
|         assert new_prng.freqstr == "M" | ||||
| @ -0,0 +1,23 @@ | ||||
| import pytest | ||||
|  | ||||
| import pandas as pd | ||||
|  | ||||
|  | ||||
| class TestResolution: | ||||
|     @pytest.mark.parametrize( | ||||
|         "freq,expected", | ||||
|         [ | ||||
|             ("Y", "year"), | ||||
|             ("Q", "quarter"), | ||||
|             ("M", "month"), | ||||
|             ("D", "day"), | ||||
|             ("h", "hour"), | ||||
|             ("min", "minute"), | ||||
|             ("s", "second"), | ||||
|             ("ms", "millisecond"), | ||||
|             ("us", "microsecond"), | ||||
|         ], | ||||
|     ) | ||||
|     def test_resolution(self, freq, expected): | ||||
|         idx = pd.period_range(start="2013-04-01", periods=30, freq=freq) | ||||
|         assert idx.resolution == expected | ||||
| @ -0,0 +1,38 @@ | ||||
| """Tests for PeriodIndex behaving like a vectorized Period scalar""" | ||||
|  | ||||
| import pytest | ||||
|  | ||||
| from pandas import ( | ||||
|     Timedelta, | ||||
|     date_range, | ||||
|     period_range, | ||||
| ) | ||||
| import pandas._testing as tm | ||||
|  | ||||
|  | ||||
| class TestPeriodIndexOps: | ||||
|     def test_start_time(self): | ||||
|         # GH#17157 | ||||
|         index = period_range(freq="M", start="2016-01-01", end="2016-05-31") | ||||
|         expected_index = date_range("2016-01-01", end="2016-05-31", freq="MS") | ||||
|         tm.assert_index_equal(index.start_time, expected_index) | ||||
|  | ||||
|     def test_end_time(self): | ||||
|         # GH#17157 | ||||
|         index = period_range(freq="M", start="2016-01-01", end="2016-05-31") | ||||
|         expected_index = date_range("2016-01-01", end="2016-05-31", freq="ME") | ||||
|         expected_index += Timedelta(1, "D") - Timedelta(1, "ns") | ||||
|         tm.assert_index_equal(index.end_time, expected_index) | ||||
|  | ||||
|     @pytest.mark.filterwarnings(r"ignore:PeriodDtype\[B\] is deprecated:FutureWarning") | ||||
|     @pytest.mark.filterwarnings( | ||||
|         "ignore:Period with BDay freq is deprecated:FutureWarning" | ||||
|     ) | ||||
|     def test_end_time_business_friday(self): | ||||
|         # GH#34449 | ||||
|         pi = period_range("1990-01-05", freq="B", periods=1) | ||||
|         result = pi.end_time | ||||
|  | ||||
|         dti = date_range("1990-01-05", freq="D", periods=1)._with_freq(None) | ||||
|         expected = dti + Timedelta(days=1, nanoseconds=-1) | ||||
|         tm.assert_index_equal(result, expected) | ||||
| @ -0,0 +1,80 @@ | ||||
| import numpy as np | ||||
| import pytest | ||||
|  | ||||
| from pandas._libs.tslibs import IncompatibleFrequency | ||||
|  | ||||
| from pandas import ( | ||||
|     NaT, | ||||
|     Period, | ||||
|     PeriodIndex, | ||||
| ) | ||||
| import pandas._testing as tm | ||||
|  | ||||
|  | ||||
| class TestSearchsorted: | ||||
|     @pytest.mark.parametrize("freq", ["D", "2D"]) | ||||
|     def test_searchsorted(self, freq): | ||||
|         pidx = PeriodIndex( | ||||
|             ["2014-01-01", "2014-01-02", "2014-01-03", "2014-01-04", "2014-01-05"], | ||||
|             freq=freq, | ||||
|         ) | ||||
|  | ||||
|         p1 = Period("2014-01-01", freq=freq) | ||||
|         assert pidx.searchsorted(p1) == 0 | ||||
|  | ||||
|         p2 = Period("2014-01-04", freq=freq) | ||||
|         assert pidx.searchsorted(p2) == 3 | ||||
|  | ||||
|         assert pidx.searchsorted(NaT) == 5 | ||||
|  | ||||
|         msg = "Input has different freq=h from PeriodArray" | ||||
|         with pytest.raises(IncompatibleFrequency, match=msg): | ||||
|             pidx.searchsorted(Period("2014-01-01", freq="h")) | ||||
|  | ||||
|         msg = "Input has different freq=5D from PeriodArray" | ||||
|         with pytest.raises(IncompatibleFrequency, match=msg): | ||||
|             pidx.searchsorted(Period("2014-01-01", freq="5D")) | ||||
|  | ||||
|     def test_searchsorted_different_argument_classes(self, listlike_box): | ||||
|         pidx = PeriodIndex( | ||||
|             ["2014-01-01", "2014-01-02", "2014-01-03", "2014-01-04", "2014-01-05"], | ||||
|             freq="D", | ||||
|         ) | ||||
|         result = pidx.searchsorted(listlike_box(pidx)) | ||||
|         expected = np.arange(len(pidx), dtype=result.dtype) | ||||
|         tm.assert_numpy_array_equal(result, expected) | ||||
|  | ||||
|         result = pidx._data.searchsorted(listlike_box(pidx)) | ||||
|         tm.assert_numpy_array_equal(result, expected) | ||||
|  | ||||
|     def test_searchsorted_invalid(self): | ||||
|         pidx = PeriodIndex( | ||||
|             ["2014-01-01", "2014-01-02", "2014-01-03", "2014-01-04", "2014-01-05"], | ||||
|             freq="D", | ||||
|         ) | ||||
|  | ||||
|         other = np.array([0, 1], dtype=np.int64) | ||||
|  | ||||
|         msg = "|".join( | ||||
|             [ | ||||
|                 "searchsorted requires compatible dtype or scalar", | ||||
|                 "value should be a 'Period', 'NaT', or array of those. Got", | ||||
|             ] | ||||
|         ) | ||||
|         with pytest.raises(TypeError, match=msg): | ||||
|             pidx.searchsorted(other) | ||||
|  | ||||
|         with pytest.raises(TypeError, match=msg): | ||||
|             pidx.searchsorted(other.astype("timedelta64[ns]")) | ||||
|  | ||||
|         with pytest.raises(TypeError, match=msg): | ||||
|             pidx.searchsorted(np.timedelta64(4)) | ||||
|  | ||||
|         with pytest.raises(TypeError, match=msg): | ||||
|             pidx.searchsorted(np.timedelta64("NaT", "ms")) | ||||
|  | ||||
|         with pytest.raises(TypeError, match=msg): | ||||
|             pidx.searchsorted(np.datetime64(4, "ns")) | ||||
|  | ||||
|         with pytest.raises(TypeError, match=msg): | ||||
|             pidx.searchsorted(np.datetime64("NaT", "ns")) | ||||
| @ -0,0 +1,363 @@ | ||||
| import numpy as np | ||||
| import pytest | ||||
|  | ||||
| import pandas as pd | ||||
| from pandas import ( | ||||
|     PeriodIndex, | ||||
|     date_range, | ||||
|     period_range, | ||||
| ) | ||||
| import pandas._testing as tm | ||||
|  | ||||
|  | ||||
| def _permute(obj): | ||||
|     return obj.take(np.random.default_rng(2).permutation(len(obj))) | ||||
|  | ||||
|  | ||||
| class TestPeriodIndex: | ||||
|     def test_union(self, sort): | ||||
|         # union | ||||
|         other1 = period_range("1/1/2000", freq="D", periods=5) | ||||
|         rng1 = period_range("1/6/2000", freq="D", periods=5) | ||||
|         expected1 = PeriodIndex( | ||||
|             [ | ||||
|                 "2000-01-06", | ||||
|                 "2000-01-07", | ||||
|                 "2000-01-08", | ||||
|                 "2000-01-09", | ||||
|                 "2000-01-10", | ||||
|                 "2000-01-01", | ||||
|                 "2000-01-02", | ||||
|                 "2000-01-03", | ||||
|                 "2000-01-04", | ||||
|                 "2000-01-05", | ||||
|             ], | ||||
|             freq="D", | ||||
|         ) | ||||
|  | ||||
|         rng2 = period_range("1/1/2000", freq="D", periods=5) | ||||
|         other2 = period_range("1/4/2000", freq="D", periods=5) | ||||
|         expected2 = period_range("1/1/2000", freq="D", periods=8) | ||||
|  | ||||
|         rng3 = period_range("1/1/2000", freq="D", periods=5) | ||||
|         other3 = PeriodIndex([], freq="D") | ||||
|         expected3 = period_range("1/1/2000", freq="D", periods=5) | ||||
|  | ||||
|         rng4 = period_range("2000-01-01 09:00", freq="h", periods=5) | ||||
|         other4 = period_range("2000-01-02 09:00", freq="h", periods=5) | ||||
|         expected4 = PeriodIndex( | ||||
|             [ | ||||
|                 "2000-01-01 09:00", | ||||
|                 "2000-01-01 10:00", | ||||
|                 "2000-01-01 11:00", | ||||
|                 "2000-01-01 12:00", | ||||
|                 "2000-01-01 13:00", | ||||
|                 "2000-01-02 09:00", | ||||
|                 "2000-01-02 10:00", | ||||
|                 "2000-01-02 11:00", | ||||
|                 "2000-01-02 12:00", | ||||
|                 "2000-01-02 13:00", | ||||
|             ], | ||||
|             freq="h", | ||||
|         ) | ||||
|  | ||||
|         rng5 = PeriodIndex( | ||||
|             ["2000-01-01 09:01", "2000-01-01 09:03", "2000-01-01 09:05"], freq="min" | ||||
|         ) | ||||
|         other5 = PeriodIndex( | ||||
|             ["2000-01-01 09:01", "2000-01-01 09:05", "2000-01-01 09:08"], freq="min" | ||||
|         ) | ||||
|         expected5 = PeriodIndex( | ||||
|             [ | ||||
|                 "2000-01-01 09:01", | ||||
|                 "2000-01-01 09:03", | ||||
|                 "2000-01-01 09:05", | ||||
|                 "2000-01-01 09:08", | ||||
|             ], | ||||
|             freq="min", | ||||
|         ) | ||||
|  | ||||
|         rng6 = period_range("2000-01-01", freq="M", periods=7) | ||||
|         other6 = period_range("2000-04-01", freq="M", periods=7) | ||||
|         expected6 = period_range("2000-01-01", freq="M", periods=10) | ||||
|  | ||||
|         rng7 = period_range("2003-01-01", freq="Y", periods=5) | ||||
|         other7 = period_range("1998-01-01", freq="Y", periods=8) | ||||
|         expected7 = PeriodIndex( | ||||
|             [ | ||||
|                 "2003", | ||||
|                 "2004", | ||||
|                 "2005", | ||||
|                 "2006", | ||||
|                 "2007", | ||||
|                 "1998", | ||||
|                 "1999", | ||||
|                 "2000", | ||||
|                 "2001", | ||||
|                 "2002", | ||||
|             ], | ||||
|             freq="Y", | ||||
|         ) | ||||
|  | ||||
|         rng8 = PeriodIndex( | ||||
|             ["1/3/2000", "1/2/2000", "1/1/2000", "1/5/2000", "1/4/2000"], freq="D" | ||||
|         ) | ||||
|         other8 = period_range("1/6/2000", freq="D", periods=5) | ||||
|         expected8 = PeriodIndex( | ||||
|             [ | ||||
|                 "1/3/2000", | ||||
|                 "1/2/2000", | ||||
|                 "1/1/2000", | ||||
|                 "1/5/2000", | ||||
|                 "1/4/2000", | ||||
|                 "1/6/2000", | ||||
|                 "1/7/2000", | ||||
|                 "1/8/2000", | ||||
|                 "1/9/2000", | ||||
|                 "1/10/2000", | ||||
|             ], | ||||
|             freq="D", | ||||
|         ) | ||||
|  | ||||
|         for rng, other, expected in [ | ||||
|             (rng1, other1, expected1), | ||||
|             (rng2, other2, expected2), | ||||
|             (rng3, other3, expected3), | ||||
|             (rng4, other4, expected4), | ||||
|             (rng5, other5, expected5), | ||||
|             (rng6, other6, expected6), | ||||
|             (rng7, other7, expected7), | ||||
|             (rng8, other8, expected8), | ||||
|         ]: | ||||
|             result_union = rng.union(other, sort=sort) | ||||
|             if sort is None: | ||||
|                 expected = expected.sort_values() | ||||
|             tm.assert_index_equal(result_union, expected) | ||||
|  | ||||
|     def test_union_misc(self, sort): | ||||
|         index = period_range("1/1/2000", "1/20/2000", freq="D") | ||||
|  | ||||
|         result = index[:-5].union(index[10:], sort=sort) | ||||
|         tm.assert_index_equal(result, index) | ||||
|  | ||||
|         # not in order | ||||
|         result = _permute(index[:-5]).union(_permute(index[10:]), sort=sort) | ||||
|         if sort is False: | ||||
|             tm.assert_index_equal(result.sort_values(), index) | ||||
|         else: | ||||
|             tm.assert_index_equal(result, index) | ||||
|  | ||||
|         # cast if different frequencies | ||||
|         index = period_range("1/1/2000", "1/20/2000", freq="D") | ||||
|         index2 = period_range("1/1/2000", "1/20/2000", freq="W-WED") | ||||
|         result = index.union(index2, sort=sort) | ||||
|         expected = index.astype(object).union(index2.astype(object), sort=sort) | ||||
|         tm.assert_index_equal(result, expected) | ||||
|  | ||||
|     def test_intersection(self, sort): | ||||
|         index = period_range("1/1/2000", "1/20/2000", freq="D") | ||||
|  | ||||
|         result = index[:-5].intersection(index[10:], sort=sort) | ||||
|         tm.assert_index_equal(result, index[10:-5]) | ||||
|  | ||||
|         # not in order | ||||
|         left = _permute(index[:-5]) | ||||
|         right = _permute(index[10:]) | ||||
|         result = left.intersection(right, sort=sort) | ||||
|         if sort is False: | ||||
|             tm.assert_index_equal(result.sort_values(), index[10:-5]) | ||||
|         else: | ||||
|             tm.assert_index_equal(result, index[10:-5]) | ||||
|  | ||||
|         # cast if different frequencies | ||||
|         index = period_range("1/1/2000", "1/20/2000", freq="D") | ||||
|         index2 = period_range("1/1/2000", "1/20/2000", freq="W-WED") | ||||
|  | ||||
|         result = index.intersection(index2, sort=sort) | ||||
|         expected = pd.Index([], dtype=object) | ||||
|         tm.assert_index_equal(result, expected) | ||||
|  | ||||
|         index3 = period_range("1/1/2000", "1/20/2000", freq="2D") | ||||
|         result = index.intersection(index3, sort=sort) | ||||
|         tm.assert_index_equal(result, expected) | ||||
|  | ||||
|     def test_intersection_cases(self, sort): | ||||
|         base = period_range("6/1/2000", "6/30/2000", freq="D", name="idx") | ||||
|  | ||||
|         # if target has the same name, it is preserved | ||||
|         rng2 = period_range("5/15/2000", "6/20/2000", freq="D", name="idx") | ||||
|         expected2 = period_range("6/1/2000", "6/20/2000", freq="D", name="idx") | ||||
|  | ||||
|         # if target name is different, it will be reset | ||||
|         rng3 = period_range("5/15/2000", "6/20/2000", freq="D", name="other") | ||||
|         expected3 = period_range("6/1/2000", "6/20/2000", freq="D", name=None) | ||||
|  | ||||
|         rng4 = period_range("7/1/2000", "7/31/2000", freq="D", name="idx") | ||||
|         expected4 = PeriodIndex([], name="idx", freq="D") | ||||
|  | ||||
|         for rng, expected in [ | ||||
|             (rng2, expected2), | ||||
|             (rng3, expected3), | ||||
|             (rng4, expected4), | ||||
|         ]: | ||||
|             result = base.intersection(rng, sort=sort) | ||||
|             tm.assert_index_equal(result, expected) | ||||
|             assert result.name == expected.name | ||||
|             assert result.freq == expected.freq | ||||
|  | ||||
|         # non-monotonic | ||||
|         base = PeriodIndex( | ||||
|             ["2011-01-05", "2011-01-04", "2011-01-02", "2011-01-03"], | ||||
|             freq="D", | ||||
|             name="idx", | ||||
|         ) | ||||
|  | ||||
|         rng2 = PeriodIndex( | ||||
|             ["2011-01-04", "2011-01-02", "2011-02-02", "2011-02-03"], | ||||
|             freq="D", | ||||
|             name="idx", | ||||
|         ) | ||||
|         expected2 = PeriodIndex(["2011-01-04", "2011-01-02"], freq="D", name="idx") | ||||
|  | ||||
|         rng3 = PeriodIndex( | ||||
|             ["2011-01-04", "2011-01-02", "2011-02-02", "2011-02-03"], | ||||
|             freq="D", | ||||
|             name="other", | ||||
|         ) | ||||
|         expected3 = PeriodIndex(["2011-01-04", "2011-01-02"], freq="D", name=None) | ||||
|  | ||||
|         rng4 = period_range("7/1/2000", "7/31/2000", freq="D", name="idx") | ||||
|         expected4 = PeriodIndex([], freq="D", name="idx") | ||||
|  | ||||
|         for rng, expected in [ | ||||
|             (rng2, expected2), | ||||
|             (rng3, expected3), | ||||
|             (rng4, expected4), | ||||
|         ]: | ||||
|             result = base.intersection(rng, sort=sort) | ||||
|             if sort is None: | ||||
|                 expected = expected.sort_values() | ||||
|             tm.assert_index_equal(result, expected) | ||||
|             assert result.name == expected.name | ||||
|             assert result.freq == "D" | ||||
|  | ||||
|         # empty same freq | ||||
|         rng = date_range("6/1/2000", "6/15/2000", freq="min") | ||||
|         result = rng[0:0].intersection(rng) | ||||
|         assert len(result) == 0 | ||||
|  | ||||
|         result = rng.intersection(rng[0:0]) | ||||
|         assert len(result) == 0 | ||||
|  | ||||
|     def test_difference(self, sort): | ||||
|         # diff | ||||
|         period_rng = ["1/3/2000", "1/2/2000", "1/1/2000", "1/5/2000", "1/4/2000"] | ||||
|         rng1 = PeriodIndex(period_rng, freq="D") | ||||
|         other1 = period_range("1/6/2000", freq="D", periods=5) | ||||
|         expected1 = rng1 | ||||
|  | ||||
|         rng2 = PeriodIndex(period_rng, freq="D") | ||||
|         other2 = period_range("1/4/2000", freq="D", periods=5) | ||||
|         expected2 = PeriodIndex(["1/3/2000", "1/2/2000", "1/1/2000"], freq="D") | ||||
|  | ||||
|         rng3 = PeriodIndex(period_rng, freq="D") | ||||
|         other3 = PeriodIndex([], freq="D") | ||||
|         expected3 = rng3 | ||||
|  | ||||
|         period_rng = [ | ||||
|             "2000-01-01 10:00", | ||||
|             "2000-01-01 09:00", | ||||
|             "2000-01-01 12:00", | ||||
|             "2000-01-01 11:00", | ||||
|             "2000-01-01 13:00", | ||||
|         ] | ||||
|         rng4 = PeriodIndex(period_rng, freq="h") | ||||
|         other4 = period_range("2000-01-02 09:00", freq="h", periods=5) | ||||
|         expected4 = rng4 | ||||
|  | ||||
|         rng5 = PeriodIndex( | ||||
|             ["2000-01-01 09:03", "2000-01-01 09:01", "2000-01-01 09:05"], freq="min" | ||||
|         ) | ||||
|         other5 = PeriodIndex(["2000-01-01 09:01", "2000-01-01 09:05"], freq="min") | ||||
|         expected5 = PeriodIndex(["2000-01-01 09:03"], freq="min") | ||||
|  | ||||
|         period_rng = [ | ||||
|             "2000-02-01", | ||||
|             "2000-01-01", | ||||
|             "2000-06-01", | ||||
|             "2000-07-01", | ||||
|             "2000-05-01", | ||||
|             "2000-03-01", | ||||
|             "2000-04-01", | ||||
|         ] | ||||
|         rng6 = PeriodIndex(period_rng, freq="M") | ||||
|         other6 = period_range("2000-04-01", freq="M", periods=7) | ||||
|         expected6 = PeriodIndex(["2000-02-01", "2000-01-01", "2000-03-01"], freq="M") | ||||
|  | ||||
|         period_rng = ["2003", "2007", "2006", "2005", "2004"] | ||||
|         rng7 = PeriodIndex(period_rng, freq="Y") | ||||
|         other7 = period_range("1998-01-01", freq="Y", periods=8) | ||||
|         expected7 = PeriodIndex(["2007", "2006"], freq="Y") | ||||
|  | ||||
|         for rng, other, expected in [ | ||||
|             (rng1, other1, expected1), | ||||
|             (rng2, other2, expected2), | ||||
|             (rng3, other3, expected3), | ||||
|             (rng4, other4, expected4), | ||||
|             (rng5, other5, expected5), | ||||
|             (rng6, other6, expected6), | ||||
|             (rng7, other7, expected7), | ||||
|         ]: | ||||
|             result_difference = rng.difference(other, sort=sort) | ||||
|             if sort is None and len(other): | ||||
|                 # We dont sort (yet?) when empty GH#24959 | ||||
|                 expected = expected.sort_values() | ||||
|             tm.assert_index_equal(result_difference, expected) | ||||
|  | ||||
|     def test_difference_freq(self, sort): | ||||
|         # GH14323: difference of Period MUST preserve frequency | ||||
|         # but the ability to union results must be preserved | ||||
|  | ||||
|         index = period_range("20160920", "20160925", freq="D") | ||||
|  | ||||
|         other = period_range("20160921", "20160924", freq="D") | ||||
|         expected = PeriodIndex(["20160920", "20160925"], freq="D") | ||||
|         idx_diff = index.difference(other, sort) | ||||
|         tm.assert_index_equal(idx_diff, expected) | ||||
|         tm.assert_attr_equal("freq", idx_diff, expected) | ||||
|  | ||||
|         other = period_range("20160922", "20160925", freq="D") | ||||
|         idx_diff = index.difference(other, sort) | ||||
|         expected = PeriodIndex(["20160920", "20160921"], freq="D") | ||||
|         tm.assert_index_equal(idx_diff, expected) | ||||
|         tm.assert_attr_equal("freq", idx_diff, expected) | ||||
|  | ||||
|     def test_intersection_equal_duplicates(self): | ||||
|         # GH#38302 | ||||
|         idx = period_range("2011-01-01", periods=2) | ||||
|         idx_dup = idx.append(idx) | ||||
|         result = idx_dup.intersection(idx_dup) | ||||
|         tm.assert_index_equal(result, idx) | ||||
|  | ||||
|     @pytest.mark.filterwarnings(r"ignore:PeriodDtype\[B\] is deprecated:FutureWarning") | ||||
|     def test_union_duplicates(self): | ||||
|         # GH#36289 | ||||
|         idx = period_range("2011-01-01", periods=2) | ||||
|         idx_dup = idx.append(idx) | ||||
|  | ||||
|         idx2 = period_range("2011-01-02", periods=2) | ||||
|         idx2_dup = idx2.append(idx2) | ||||
|         result = idx_dup.union(idx2_dup) | ||||
|  | ||||
|         expected = PeriodIndex( | ||||
|             [ | ||||
|                 "2011-01-01", | ||||
|                 "2011-01-01", | ||||
|                 "2011-01-02", | ||||
|                 "2011-01-02", | ||||
|                 "2011-01-03", | ||||
|                 "2011-01-03", | ||||
|             ], | ||||
|             freq="D", | ||||
|         ) | ||||
|         tm.assert_index_equal(result, expected) | ||||
| @ -0,0 +1,52 @@ | ||||
| import numpy as np | ||||
| import pytest | ||||
|  | ||||
| from pandas import ( | ||||
|     Period, | ||||
|     PeriodIndex, | ||||
|     period_range, | ||||
| ) | ||||
| import pandas._testing as tm | ||||
|  | ||||
|  | ||||
| class TestPeriodRepresentation: | ||||
|     """ | ||||
|     Wish to match NumPy units | ||||
|     """ | ||||
|  | ||||
|     @pytest.mark.parametrize( | ||||
|         "freq, base_date", | ||||
|         [ | ||||
|             ("W-THU", "1970-01-01"), | ||||
|             ("D", "1970-01-01"), | ||||
|             ("B", "1970-01-01"), | ||||
|             ("h", "1970-01-01"), | ||||
|             ("min", "1970-01-01"), | ||||
|             ("s", "1970-01-01"), | ||||
|             ("ms", "1970-01-01"), | ||||
|             ("us", "1970-01-01"), | ||||
|             ("ns", "1970-01-01"), | ||||
|             ("M", "1970-01"), | ||||
|             ("Y", 1970), | ||||
|         ], | ||||
|     ) | ||||
|     @pytest.mark.filterwarnings(r"ignore:PeriodDtype\[B\] is deprecated:FutureWarning") | ||||
|     @pytest.mark.filterwarnings( | ||||
|         "ignore:Period with BDay freq is deprecated:FutureWarning" | ||||
|     ) | ||||
|     def test_freq(self, freq, base_date): | ||||
|         rng = period_range(start=base_date, periods=10, freq=freq) | ||||
|         exp = np.arange(10, dtype=np.int64) | ||||
|  | ||||
|         tm.assert_numpy_array_equal(rng.asi8, exp) | ||||
|  | ||||
|  | ||||
| class TestPeriodIndexConversion: | ||||
|     def test_tolist(self): | ||||
|         index = period_range(freq="Y", start="1/1/2001", end="12/1/2009") | ||||
|         rs = index.tolist() | ||||
|         for x in rs: | ||||
|             assert isinstance(x, Period) | ||||
|  | ||||
|         recon = PeriodIndex(rs) | ||||
|         tm.assert_index_equal(index, recon) | ||||
		Reference in New Issue
	
	Block a user