Skip to content

Commit 2856c64

Browse files
committed
BUG: DateRange / subclass handling in Index.join. Handle name field in Index.union, GH pandas-dev#500, pandas-dev#501
1 parent 4c1547f commit 2856c64

File tree

3 files changed

+64
-35
lines changed

3 files changed

+64
-35
lines changed

pandas/core/daterange.py

Lines changed: 47 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -286,6 +286,30 @@ def union(self, other):
286286
if not isinstance(other, DateRange) or other.offset != self.offset:
287287
return Index.union(self.view(Index), other)
288288

289+
if self._can_fast_union(other):
290+
return self._fast_union(other)
291+
else:
292+
return Index.union(self, other)
293+
294+
def _wrap_union_result(self, other, result):
295+
name = self.name if self.name == other.name else None
296+
if isinstance(other, DateRange) and self._can_fast_union(other):
297+
result = self._view_like(result)
298+
result.name = name
299+
return result
300+
else:
301+
return Index(result, name=name)
302+
303+
def _wrap_joined_index(self, joined, other):
304+
name = self.name if self.name == other.name else None
305+
if isinstance(other, DateRange) and self._can_fast_union(other):
306+
joined = self._view_like(joined)
307+
joined.name = name
308+
return joined
309+
else:
310+
return Index(joined, name=name)
311+
312+
def _can_fast_union(self, other):
289313
offset = self.offset
290314

291315
# to make our life easier, "sort" the two ranges
@@ -298,10 +322,30 @@ def union(self, other):
298322
right_start = right[0]
299323

300324
# Only need to "adjoin", not overlap
301-
if (left_end + offset) >= right_start:
302-
return left._fast_union(right)
325+
return (left_end + offset) >= right_start
326+
327+
def _fast_union(self, other):
328+
# to make our life easier, "sort" the two ranges
329+
if self[0] <= other[0]:
330+
left, right = self, other
303331
else:
304-
return Index.union(self, other)
332+
left, right = other, self
333+
334+
left_start, left_end = left[0], left[-1]
335+
right_end = right[-1]
336+
337+
if not _will_use_cache(self.offset):
338+
# concatenate dates
339+
if left_end < right_end:
340+
loc = right.searchsorted(left_end, side='right')
341+
right_chunk = right.values[loc:]
342+
dates = np.concatenate((left.values, right_chunk))
343+
return self._view_like(dates)
344+
else:
345+
return left
346+
else:
347+
return DateRange(left_start, max(left_end, right_end),
348+
offset=left.offset)
305349

306350
def intersection(self, other):
307351
"""
@@ -335,35 +379,13 @@ def intersection(self, other):
335379
left_chunk = left.values[lslice]
336380
return self._view_like(left_chunk)
337381

338-
def _fast_union(self, other):
339-
left, right = self, other
340-
341-
left_start, left_end = left[0], left[-1]
342-
right_end = right[-1]
343-
344-
if not _will_use_cache(self.offset):
345-
# concatenate dates
346-
if left_end < right_end:
347-
loc = right.searchsorted(left_end, side='right')
348-
right_chunk = right.values[loc:]
349-
dates = np.concatenate((left.values, right_chunk))
350-
return self._view_like(dates)
351-
else:
352-
return left
353-
else:
354-
return DateRange(left_start, max(left_end, right_end),
355-
offset=left.offset)
356-
357382
def _view_like(self, ndarray):
358383
result = ndarray.view(DateRange)
359384
result.offset = self.offset
360385
result.tzinfo = self.tzinfo
361386
result.name = self.name
362387
return result
363388

364-
def _wrap_union_result(self, other, result):
365-
return Index(result)
366-
367389
def tz_normalize(self, tz):
368390
"""
369391
Convert DateRange from one time zone to another (using pytz)

pandas/core/index.py

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -378,10 +378,11 @@ def union(self, other):
378378
return self._wrap_union_result(other, result)
379379

380380
def _wrap_union_result(self, other, result):
381+
name = self.name if self.name == other.name else None
381382
if type(self) == type(other):
382-
return type(self)(result)
383+
return type(self)(result, name=name)
383384
else:
384-
return Index(result)
385+
return Index(result, name=name)
385386

386387
def intersection(self, other):
387388
"""
@@ -586,12 +587,6 @@ def join(self, other, how='left', return_indexers=False):
586587
return join_index
587588

588589
def _join_monotonic(self, other, how='left', return_indexers=False):
589-
this_vals = self.values
590-
591-
# if self.dtype != other.dtype:
592-
# other = Index(other, dtype=object)
593-
other_vals = other.values
594-
595590
if how == 'left':
596591
join_index = self
597592
lidx = None
@@ -601,10 +596,12 @@ def _join_monotonic(self, other, how='left', return_indexers=False):
601596
lidx = self._left_indexer(other, self)
602597
ridx = None
603598
elif how == 'inner':
604-
join_index, lidx, ridx = self._inner_indexer(this_vals, other_vals)
599+
join_index, lidx, ridx = self._inner_indexer(self.values,
600+
other.values)
605601
join_index = self._wrap_joined_index(join_index, other)
606602
elif how == 'outer':
607-
join_index, lidx, ridx = self._outer_indexer(this_vals, other_vals)
603+
join_index, lidx, ridx = self._outer_indexer(self.values,
604+
other.values)
608605
join_index = self._wrap_joined_index(join_index, other)
609606
else: # pragma: no cover
610607
raise Exception('do not recognize join method %s' % how)

pandas/tests/test_index.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,16 @@ def test_union(self):
175175
# non-iterable input
176176
self.assertRaises(Exception, first.union, 0.5)
177177

178+
# preserve names
179+
first.name = 'A'
180+
second.name = 'A'
181+
union = first.union(second)
182+
self.assert_(union.name == 'A')
183+
184+
second.name = 'B'
185+
union = first.union(second)
186+
self.assert_(union.name is None)
187+
178188
def test_add(self):
179189
firstCat = self.strIndex + self.dateIndex
180190
secondCat = self.strIndex + self.strIndex

0 commit comments

Comments
 (0)