From f765d21f9e9a40b6212778bffe3f78c9e0477ca2 Mon Sep 17 00:00:00 2001 From: Tom Augspurger Date: Fri, 2 Nov 2018 09:30:21 -0700 Subject: [PATCH] BUG: Allow freq conversion from dt64 to period Closes #23438 --- pandas/core/arrays/period.py | 23 ++++++------------- pandas/tests/arrays/test_period.py | 9 +++++--- .../tests/indexes/period/test_construction.py | 15 ++++++++++++ 3 files changed, 28 insertions(+), 19 deletions(-) diff --git a/pandas/core/arrays/period.py b/pandas/core/arrays/period.py index 1bbad4b73953d..90e7beac63427 100644 --- a/pandas/core/arrays/period.py +++ b/pandas/core/arrays/period.py @@ -967,24 +967,15 @@ def dt64arr_to_periodarr(data, freq, tz=None): if data.dtype != np.dtype('M8[ns]'): raise ValueError('Wrong dtype: %s' % data.dtype) - if freq is not None: - freq = Period._maybe_convert_freq(freq) + if freq is None: + if isinstance(data, ABCIndexClass): + data, freq = data._values, data.freq + elif isinstance(data, ABCSeries): + data, freq = data._values, data.dt.freq - if isinstance(data, ABCIndexClass): - if freq is None: - freq = data.freq - elif freq != data.freq: - msg = DIFFERENT_FREQ_INDEX.format(freq.freqstr, data.freq.freqstr) - raise IncompatibleFrequency(msg) - data = data._values + freq = Period._maybe_convert_freq(freq) - elif isinstance(data, ABCSeries): - if freq is None: - freq = data.dt.freq - elif freq != data.dt.freq: - msg = DIFFERENT_FREQ_INDEX.format(freq.freqstr, - data.dt.freq.freqstr) - raise IncompatibleFrequency(msg) + if isinstance(data, (ABCIndexClass, ABCSeries)): data = data._values base, mult = frequencies.get_freq_code(freq) diff --git a/pandas/tests/arrays/test_period.py b/pandas/tests/arrays/test_period.py index 40bdd4f1aaa5c..0125729048cdd 100644 --- a/pandas/tests/arrays/test_period.py +++ b/pandas/tests/arrays/test_period.py @@ -34,10 +34,13 @@ def test_period_array_ok(data, freq, expected): tm.assert_numpy_array_equal(result, expected) -def test_from_datetime64_raises(): +def test_from_datetime64_freq_changes(): + # https://github.com/pandas-dev/pandas/issues/23438 arr = pd.date_range("2017", periods=3, freq="D") - with tm.assert_raises_regex(IncompatibleFrequency, "freq"): - PeriodArray._from_datetime64(arr, freq="M") + result = PeriodArray._from_datetime64(arr, freq="M") + expected = period_array(['2017-01-01', '2017-01-01', '2017-01-01'], + freq="M") + tm.assert_period_array_equal(result, expected) @pytest.mark.parametrize("data, freq, msg", [ diff --git a/pandas/tests/indexes/period/test_construction.py b/pandas/tests/indexes/period/test_construction.py index 9622f47697f8d..fb74244d815c2 100644 --- a/pandas/tests/indexes/period/test_construction.py +++ b/pandas/tests/indexes/period/test_construction.py @@ -158,6 +158,21 @@ def test_constructor_datetime64arr(self): pytest.raises(ValueError, PeriodIndex, vals, freq='D') + @pytest.mark.parametrize('box', [None, 'series', 'index']) + def test_constructor_datetime64arr_ok(self, box): + # https://github.com/pandas-dev/pandas/issues/23438 + data = pd.date_range('2017', periods=4, freq="M") + if box is None: + data = data._values + elif box == 'series': + data = pd.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]')