Skip to content

Commit 7042d06

Browse files
reidy-pPingviinituutti
authored andcommitted
ENH: Add in sort keyword to DatetimeIndex.union (pandas-dev#25110)
1 parent 72ddc11 commit 7042d06

File tree

4 files changed

+123
-54
lines changed

4 files changed

+123
-54
lines changed

doc/source/styled.xlsx

5.55 KB
Binary file not shown.

doc/source/whatsnew/v0.25.0.rst

+1
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ Other Enhancements
2222
- Indexing of ``DataFrame`` and ``Series`` now accepts zerodim ``np.ndarray`` (:issue:`24919`)
2323
- :meth:`Timestamp.replace` now supports the ``fold`` argument to disambiguate DST transition times (:issue:`25017`)
2424
- :meth:`DataFrame.at_time` and :meth:`Series.at_time` now support :meth:`datetime.time` objects with timezones (:issue:`24043`)
25+
- :meth:`DatetimeIndex.union` now supports the ``sort`` argument. The behaviour of the sort parameter matches that of :meth:`Index.union` (:issue:`24994`)
2526
-
2627

2728
.. _whatsnew_0250.api_breaking:

pandas/core/indexes/datetimes.py

+32-6
Original file line numberDiff line numberDiff line change
@@ -460,7 +460,7 @@ def _formatter_func(self):
460460
# --------------------------------------------------------------------
461461
# Set Operation Methods
462462

463-
def union(self, other):
463+
def union(self, other, sort=None):
464464
"""
465465
Specialized union for DatetimeIndex objects. If combine
466466
overlapping ranges with the same DateOffset, will be much
@@ -469,15 +469,29 @@ def union(self, other):
469469
Parameters
470470
----------
471471
other : DatetimeIndex or array-like
472+
sort : bool or None, default None
473+
Whether to sort the resulting Index.
474+
475+
* None : Sort the result, except when
476+
477+
1. `self` and `other` are equal.
478+
2. `self` or `other` has length 0.
479+
3. Some values in `self` or `other` cannot be compared.
480+
A RuntimeWarning is issued in this case.
481+
482+
* False : do not sort the result
483+
484+
.. versionadded:: 0.25.0
472485
473486
Returns
474487
-------
475488
y : Index or DatetimeIndex
476489
"""
490+
self._validate_sort_keyword(sort)
477491
self._assert_can_do_setop(other)
478492

479493
if len(other) == 0 or self.equals(other) or len(self) == 0:
480-
return super(DatetimeIndex, self).union(other)
494+
return super(DatetimeIndex, self).union(other, sort=sort)
481495

482496
if not isinstance(other, DatetimeIndex):
483497
try:
@@ -488,9 +502,9 @@ def union(self, other):
488502
this, other = self._maybe_utc_convert(other)
489503

490504
if this._can_fast_union(other):
491-
return this._fast_union(other)
505+
return this._fast_union(other, sort=sort)
492506
else:
493-
result = Index.union(this, other)
507+
result = Index.union(this, other, sort=sort)
494508
if isinstance(result, DatetimeIndex):
495509
# TODO: we shouldn't be setting attributes like this;
496510
# in all the tests this equality already holds
@@ -563,16 +577,28 @@ def _can_fast_union(self, other):
563577
# this will raise
564578
return False
565579

566-
def _fast_union(self, other):
580+
def _fast_union(self, other, sort=None):
567581
if len(other) == 0:
568582
return self.view(type(self))
569583

570584
if len(self) == 0:
571585
return other.view(type(self))
572586

573-
# to make our life easier, "sort" the two ranges
587+
# Both DTIs are monotonic. Check if they are already
588+
# in the "correct" order
574589
if self[0] <= other[0]:
575590
left, right = self, other
591+
# DTIs are not in the "correct" order and we don't want
592+
# to sort but want to remove overlaps
593+
elif sort is False:
594+
left, right = self, other
595+
left_start = left[0]
596+
loc = right.searchsorted(left_start, side='left')
597+
right_chunk = right.values[:loc]
598+
dates = _concat._concat_compat((left.values, right_chunk))
599+
return self._shallow_copy(dates)
600+
# DTIs are not in the "correct" order and we want
601+
# to sort
576602
else:
577603
left, right = other, self
578604

0 commit comments

Comments
 (0)