From f7e087df971ad4d3fa08929f58544378e11c30df Mon Sep 17 00:00:00 2001 From: Matt Roeschke Date: Tue, 19 Mar 2019 23:44:10 -0700 Subject: [PATCH 1/2] Add test for when freq are the same but not continuous --- doc/source/whatsnew/v0.25.0.rst | 2 +- pandas/core/indexes/datetimelike.py | 8 ++++++-- pandas/tests/reshape/test_concat.py | 17 +++++++++++++++++ 3 files changed, 24 insertions(+), 3 deletions(-) diff --git a/doc/source/whatsnew/v0.25.0.rst b/doc/source/whatsnew/v0.25.0.rst index 73eb6a15a1b47..0431a73546f06 100644 --- a/doc/source/whatsnew/v0.25.0.rst +++ b/doc/source/whatsnew/v0.25.0.rst @@ -300,7 +300,7 @@ Reshaping - Bug in :func:`merge` when merging by index name would sometimes result in an incorrectly numbered index (:issue:`24212`) - :func:`to_records` now accepts dtypes to its `column_dtypes` parameter (:issue:`24895`) - Bug in :func:`concat` where order of ``OrderedDict`` (and ``dict`` in Python 3.6+) is not respected, when passed in as ``objs`` argument (:issue:`21510`) - +- Bug in :func:`concat` where the resulting ``freq`` of two :class:`DatetimeIndex` with the same ``freq`` would be dropped (:issue:`3232`). Sparse ^^^^^^ diff --git a/pandas/core/indexes/datetimelike.py b/pandas/core/indexes/datetimelike.py index 830f234b85757..eee48108f8d37 100644 --- a/pandas/core/indexes/datetimelike.py +++ b/pandas/core/indexes/datetimelike.py @@ -587,11 +587,15 @@ def _concat_same_dtype(self, to_concat, name): if len({str(x.dtype) for x in to_concat}) != 1: raise ValueError('to_concat must have the same tz') - if not is_period_dtype(self): + new_data = type(self._values)._concat_same_type(to_concat).asi8 + + # GH 3232: If the concat result is evenly spaced, we can retain the + # original frequency + is_diff_evenly_spaced = len(np.unique(np.diff(new_data))) == 1 + if not is_period_dtype(self) and not is_diff_evenly_spaced: # reset freq attribs['freq'] = None - new_data = type(self._values)._concat_same_type(to_concat).asi8 return self._simple_new(new_data, **attribs) @Appender(_index_shared_docs['astype']) diff --git a/pandas/tests/reshape/test_concat.py b/pandas/tests/reshape/test_concat.py index ccd50998e39b1..2243a31289f72 100644 --- a/pandas/tests/reshape/test_concat.py +++ b/pandas/tests/reshape/test_concat.py @@ -2539,3 +2539,20 @@ def test_concat_categorical_tz(): 'a', 'b' ]) tm.assert_series_equal(result, expected) + + +def test_concat_datetimeindex_freq(): + # GH 3232 + # Monotonic index result + dr = pd.date_range('01-Jan-2013', periods=100, freq='50L', tz='UTC') + data = list(range(100)) + expected = pd.DataFrame(data, index=dr) + result = pd.concat([expected[:50], expected[50:]]) + tm.assert_frame_equal(result, expected) + + # Non-monotonic index result + result = pd.concat([expected[50:], expected[:50]]) + expected = pd.DataFrame(data[50:] + data[:50], + index=dr[50:].append(dr[:50])) + expected.index.freq = None + tm.assert_frame_equal(result, expected) From b8a9ed734e5a17aaf7393975ca3b575b330fd7d9 Mon Sep 17 00:00:00 2001 From: Matt Roeschke Date: Mon, 25 Mar 2019 16:06:10 -0700 Subject: [PATCH 2/2] use unique_deltas --- pandas/core/indexes/datetimelike.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pandas/core/indexes/datetimelike.py b/pandas/core/indexes/datetimelike.py index eee48108f8d37..da4e7040097a2 100644 --- a/pandas/core/indexes/datetimelike.py +++ b/pandas/core/indexes/datetimelike.py @@ -8,6 +8,7 @@ import numpy as np from pandas._libs import NaT, iNaT, lib +from pandas._libs.algos import unique_deltas from pandas.compat.numpy import function as nv from pandas.errors import AbstractMethodError from pandas.util._decorators import Appender, cache_readonly, deprecate_kwarg @@ -591,7 +592,7 @@ def _concat_same_dtype(self, to_concat, name): # GH 3232: If the concat result is evenly spaced, we can retain the # original frequency - is_diff_evenly_spaced = len(np.unique(np.diff(new_data))) == 1 + is_diff_evenly_spaced = len(unique_deltas(new_data)) == 1 if not is_period_dtype(self) and not is_diff_evenly_spaced: # reset freq attribs['freq'] = None