Skip to content
This repository was archived by the owner on Dec 22, 2019. It is now read-only.
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
105 changes: 56 additions & 49 deletions pandas/core/indexes/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
ensure_index_from_sequences,
InvalidIndexError) # noqa
from pandas.core.indexes.category import CategoricalIndex # noqa
from pandas.core.indexes.frozen import FrozenList
from pandas.core.indexes.multi import MultiIndex # noqa
from pandas.core.indexes.interval import IntervalIndex # noqa
from pandas.core.indexes.numeric import (NumericIndex, Float64Index, # noqa
Expand Down Expand Up @@ -95,9 +96,7 @@ def _get_combined_index(indexes, intersect=False, sort=False):
elif len(indexes) == 1:
index = indexes[0]
elif intersect:
index = indexes[0]
for other in indexes[1:]:
index = index.intersection(other)
index = _intersect_indexes(indexes)
else:
index = _union_indexes(indexes, sort=sort)
index = ensure_index(index)
Expand All @@ -110,6 +109,17 @@ def _get_combined_index(indexes, intersect=False, sort=False):
return index


def _intersect_indexes(indexes):
"""Return the intersection of indexes

Preserves the order of the first index.
"""
index = indexes[0]
for other in indexes[1:]:
index = index.intersection(other)
return index


def _union_indexes(indexes, sort=True):
"""Return the union of indexes

Expand All @@ -125,15 +135,6 @@ def _union_indexes(indexes, sort=True):
-------
Index
"""
if len(indexes) == 0:
raise AssertionError('Must have at least 1 Index to union')
if len(indexes) == 1:
result = indexes[0]
if isinstance(result, list):
result = Index(sorted(result))
return result

indexes, kind = _sanitize_and_check(indexes)

def _unique_indices(inds):
"""Convert indexes to lists and concatenate them, removing duplicates
Expand All @@ -153,35 +154,46 @@ def conv(i):
i = i.tolist()
return i

return Index(
lib.fast_unique_multiple_list([conv(i) for i in inds], sort=sort))
inds = [conv(i) for i in inds]
ind_values = lib.fast_unique_multiple_list(inds, sort=sort)
return Index(ind_values)

if kind == 'special':
if len(indexes) == 0:
raise AssertionError('Must have at least 1 Index to union')
if len(indexes) == 1:
result = indexes[0]
if isinstance(result, list):
result = Index(sorted(result))
return result

indexes, kind = _sanitize_and_check(indexes)

if kind == 'special':

result = indexes[0]
if hasattr(result, 'union_many'):
return result.union_many(indexes[1:])
else:
for other in indexes[1:]:
result = result.union(other)
return result
elif kind == 'array':
index = indexes[0]
for other in indexes[1:]:
if not index.equals(other):

if sort is None:
# TODO: remove once pd.concat sort default changes
warnings.warn(_sort_msg, FutureWarning, stacklevel=8)
sort = True
elif kind == 'array':

return _unique_indices(indexes)
if _all_indexes_same(indexes):
index = indexes[0]
name = _get_consensus_names(indexes)[0]
if name != index.name:
index = index._shallow_copy(name=name)
return index
else:
if sort is None:
# TODO: remove once pd.concat sort default changes
warnings.warn(_sort_msg, FutureWarning, stacklevel=8)
sort = True
return _unique_indices(indexes)

name = _get_consensus_names(indexes)[0]
if name != index.name:
index = index._shallow_copy(name=name)
return index
else: # kind='list'
else: # kind == 'list'
return _unique_indices(indexes)


Expand All @@ -205,18 +217,18 @@ def _sanitize_and_check(indexes):
sanitized_indexes: list of Index or array-like objects
type: {'list', 'array', 'special'}
"""
kinds = list({type(index) for index in indexes})
kinds = {type(index) for index in indexes}

if list in kinds:
if len(kinds) > 1:
indexes = [Index(com.try_sort(x))
if not isinstance(x, Index) else
x for x in indexes]
kinds.remove(list)
else:
if len(kinds) == 1:
return indexes, 'list'
else:
indexes = [Index(com.try_sort(i))
if not isinstance(i, Index) else i
for i in indexes]
kinds.remove(list)

if len(kinds) > 1 or Index not in kinds:
if any(kind != Index for kind in kinds):
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not accounting len(kinds) == 0

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it's okay

return indexes, 'special'
else:
return indexes, 'array'
Expand All @@ -237,14 +249,11 @@ def _get_consensus_names(indexes):
list
A list representing the consensus 'names' found
"""

# find the non-none names, need to tupleify to make
# the set hashable, then reverse on return
consensus_names = {tuple(i.names) for i in indexes
if com._any_not_none(*i.names)}
if len(consensus_names) == 1:
return list(list(consensus_names)[0])
return [None] * indexes[0].nlevels
non_empty = {i.names for i in indexes if com._any_not_none(*i.names)}
if len(non_empty) == 1:
return non_empty.pop()
else:
return FrozenList([None] * indexes[0].nlevels)


def _all_indexes_same(indexes):
Expand All @@ -260,7 +269,5 @@ def _all_indexes_same(indexes):
True if all indexes contain the same elements, False otherwise
"""
first = indexes[0]
for index in indexes[1:]:
if not first.equals(index):
return False
return True
others = indexes[1:]
return all(first.equals(other) for other in others)