Skip to content

REGR: preserve freq in DTI/TDI outer join #32166

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 10 commits into from
Feb 26, 2020
1 change: 1 addition & 0 deletions doc/source/whatsnew/v1.0.2.rst
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ Fixed regressions
- Fixed regression where :func:`read_pickle` raised a ``UnicodeDecodeError`` when reading a py27 pickle with :class:`MultiIndex` column (:issue:`31988`).
- Fixed regression in :class:`DataFrame` arithmetic operations with mis-matched columns (:issue:`31623`)
- Fixed regression in :meth:`GroupBy.agg` calling a user-provided function an extra time on an empty input (:issue:`31760`)
- Joining on :class:`DatetimeIndex` or :class:`TimedeltaIndex` will preserve ``freq`` in simple cases (:issue:`32166`)
-

.. ---------------------------------------------------------------------------
Expand Down
17 changes: 7 additions & 10 deletions pandas/core/indexes/datetimelike.py
Original file line number Diff line number Diff line change
Expand Up @@ -910,17 +910,14 @@ def _is_convertible_to_index_for_join(cls, other: Index) -> bool:
return True
return False

def _wrap_joined_index(self, joined, other):
def _wrap_joined_index(self, joined: np.ndarray, other):
assert other.dtype == self.dtype, (other.dtype, self.dtype)
name = get_op_result_name(self, other)
if self._can_fast_union(other):
joined = self._shallow_copy(joined)
joined.name = name
return joined
else:
kwargs = {}
if hasattr(self, "tz"):
kwargs["tz"] = getattr(other, "tz", None)
return type(self)._simple_new(joined, name, **kwargs)

freq = self.freq if self._can_fast_union(other) else None
new_data = type(self._data)._simple_new(joined, dtype=self.dtype, freq=freq)

return type(self)._simple_new(new_data, name=name)

# --------------------------------------------------------------------
# List-Like Methods
Expand Down
13 changes: 13 additions & 0 deletions pandas/tests/indexes/datetimes/test_join.py
Original file line number Diff line number Diff line change
Expand Up @@ -129,3 +129,16 @@ def test_naive_aware_conflicts(self):

with pytest.raises(TypeError, match=msg):
aware.join(naive)

@pytest.mark.parametrize("tz", [None, "US/Pacific"])
def test_join_preserves_freq(self, tz):
# GH#32157
dti = date_range("2016-01-01", periods=10, tz=tz)
result = dti[:5].join(dti[5:], how="outer")
assert result.freq == dti.freq
tm.assert_index_equal(result, dti)

result = dti[:5].join(dti[6:], how="outer")
assert result.freq is None
expected = dti.delete(5)
tm.assert_index_equal(result, expected)
12 changes: 12 additions & 0 deletions pandas/tests/indexes/timedeltas/test_join.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,3 +35,15 @@ def test_does_not_convert_mixed_integer(self):
assert cols.dtype == np.dtype("O")
assert cols.dtype == joined.dtype
tm.assert_index_equal(cols, joined)

def test_join_preserves_freq(self):
# GH#32157
tdi = timedelta_range("1 day", periods=10)
result = tdi[:5].join(tdi[5:], how="outer")
assert result.freq == tdi.freq
tm.assert_index_equal(result, tdi)

result = tdi[:5].join(tdi[6:], how="outer")
assert result.freq is None
expected = tdi.delete(5)
tm.assert_index_equal(result, expected)