HOME


sh-3ll 1.0
DIR:/usr/local/lib64/python3.6/site-packages/pandas/core/indexes/__pycache__/
Upload File :
Current File : //usr/local/lib64/python3.6/site-packages/pandas/core/indexes/__pycache__/multi.cpython-36.pyc
3

���h"��@s�ddlmZddlmZmZmZmZmZmZm	Z	m
Z
mZmZddl
Z
ddlZddlmZddlmZmZmZddlmZddlmZmZddlmZdd	l m!Z!m"Z"m#Z#dd
l$m%Z%m&Z&m'Z'ddl(m)Z)ddl*m+Z+m,Z,m-Z-m.Z.m/Z/m0Z0m1Z1m2Z2m3Z3m4Z4dd
l5m6Z6ddl7m8Z8m9Z9m:Z:ddl;m<Z<m=Z=ddl>j?j@ZddlAmBZBddlCmDZDddlEj?jFZGddlHj?jIjJZKddlHmLZLmMZMmNZNddlOmPZPddlQmRZRddlSj?jTZTddlUmVZVmWZWmXZXddlYmZZZm[Z[m\Z\e�r�ddl]m^Z^e_eKj`�Z`e`jae_ddd��Gdd�dejbejc�ZdGdd�dejbeje�ZfGdd�deL�Zgegjh�egji�egjj�d-ekd!�d"d#�Zlemd$�d%d&�Znd'd(�Zod.epejqd*�d+d,�ZrdS)/�)�	getsizeof)
�
TYPE_CHECKING�Any�Callable�Hashable�Iterable�List�Optional�Sequence�Tuple�UnionN)�
get_option)�algos�index�lib)�duplicated_int64)�AnyArrayLike�Scalar)�function)�InvalidIndexError�PerformanceWarning�UnsortedIndexError)�Appender�cache_readonly�doc)�coerce_indexer_dtype)
�ensure_int64�ensure_platform_int�is_categorical_dtype�is_hashable�
is_integer�is_iterator�is_list_like�is_object_dtype�	is_scalar�pandas_dtype)�ExtensionDtype)�ABCDataFrame�ABCDatetimeIndex�ABCTimedeltaIndex)�array_equivalent�isna)�Categorical)�factorize_from_iterables)�Index�_index_shared_docs�ensure_index)�
FrozenList)�
Int64Index)�get_group_index�indexer_from_factorized�lexsort_indexer)�format_object_attrs�format_object_summary�pprint_thing)�Series�
MultiIndexzMultiIndex or list of tuples)�klassZtarget_klassc@seZdZdZejZdd�ZdS)�MultiIndexUIntEngineza
    This class manages a MultiIndex by mapping label combinations to positive
    integers.
    cCs0||jK}|jdkr tjj|�Stjj|dd�S)a
        Transform combination(s) of uint64 in one uint64 (each), in a strictly
        monotonic way (i.e. respecting the lexicographic order of integer
        combinations): see BaseMultiIndexCodesEngine documentation.

        Parameters
        ----------
        codes : 1- or 2-dimensional array of dtype uint64
            Combinations of integers (one per row)

        Returns
        -------
        scalar or 1-dimensional array, of dtype uint64
            Integer(s) representing one combination (each).
        �)�axis)�offsets�ndim�np�
bitwise_or�reduce)�self�codes�rF�;/tmp/pip-build-5_djhm0z/pandas/pandas/core/indexes/multi.py�_codes_to_intsRs

z#MultiIndexUIntEngine._codes_to_intsN)�__name__�
__module__�__qualname__�__doc__�libindex�UInt64Engine�_baserHrFrFrFrGr<Jsr<c@seZdZdZejZdd�ZdS)�MultiIndexPyIntEnginez�
    This class manages those (extreme) cases in which the number of possible
    label combinations overflows the 64 bits integers, and uses an ObjectEngine
    containing Python integers.
    cCs6|jd�|j>}|jdkr&tjj|�Stjj|dd�S)a
        Transform combination(s) of uint64 in one Python integer (each), in a
        strictly monotonic way (i.e. respecting the lexicographic order of
        integer combinations): see BaseMultiIndexCodesEngine documentation.

        Parameters
        ----------
        codes : 1- or 2-dimensional array of dtype uint64
            Combinations of integers (one per row)

        Returns
        -------
        int, or 1-dimensional array of dtype object
            Integer(s) representing one combination (each).
        �objectr=)r>)�astyper?r@rArBrC)rDrErFrFrGrHzs
z$MultiIndexPyIntEngine._codes_to_intsN)rIrJrKrLrM�ObjectEnginerOrHrFrFrFrGrPqsrPc	s�eZdZUdZeje�BZdZe�Z	e�Z
e�ZdgZej
ZdZeed�eed�dd	�Zeed
�dd�Zd�eeeed
�dd�Zedejfdd�dd��Zed�dd��Zedejfdd��Zed�dd��Zedd��Z edd��Z!edd��Z"edd ��Z#ed�d!d"�Z$e%d#d$��Z&d�d%d&�Z'd�d'd(�Z(eed�d)d*��Z)ed+d,��Z*ed-d.��Z+d�d/d0�Z,d�d1d2�Z-e%d3d4��Z.ed5d6��Z/e0ej1�dejddddejdfed7�d8d9��Z1d�d:d;�Z2�dd<d=�Z3�de4j5d�d>d?�Z6�dd@dA�Z7e0ej8�e9edB�dCdD��Z8e%e4j:d�dEdF��Z:ed�dGdH�Z;e0ej<��deedI�dJdK��Z<e%ed�dLdM��Z=�deedI�dNdO�Z>dPdQ�Z?�ddRdS�Z@dTdU�ZA�ddWdX�ZB�deeeeCeeDeeeedZ�d[d\�ZEd]d^�ZF�dd_d`�ZGeeGeFdadb�ZHe0ejI�dcdd��ZIe%eDd�dedf��ZJed�dgdh�ZKeed�didj��ZLe%ed�dkdl��ZMe%ed�dmdn��ZNe%dodp��ZOe0ejP��d	drds��ZP�d
dtdu�ZQe0ejR��ddwdx��ZR�ddydz�ZSd{d|�ZTe0ejU��d
�fd}d~�	�ZUdd��ZV�dd�d��ZWd�d��ZXeed�d�d���ZYed�d�d��ZZe%d�d���Z[ed�d�d��Z\d�d��Z]d�d��Z^d�d��Z_d�d��Z`eaebd�ec��dd�d���Zd�dd�d��Zed�d��Zfe4j5d�d�d��Zgeaebd�ec��dd�d���Zh�dd�d��Zi�dd�d��Zj�dd�d��Zk�dd�d��Zld�d��Zmd�d��Zn�dd�d��Zo�dd�d��Zpd�d��Zqed�d�d��Zrd�d��d�d��Zs�fd�d��Ztd�d��Zueaebd�ec��dd�d„�Zveaebd�ec��fd�dń�ZwexeyezeyfeDeDedƜd�dȄZ{�d�fd�dʄ	Z|�dd�d̈́Z}eeyedΜd�dЄZ~�dd�d҄Z�dedӜd�dՄZ��dd�dׄZ�d�dلZ�e�exe�e�e�fd�fe�e�dۜd�d݄Z��d d�d߄Z�ed�d�d�Z�ed�d�d�Z��d!d�d�Z��d"d�d�Z��d#d�d�Z�d�d�Z�e0ej���d$d�d��Z�ed�d�d�Z�d�d�Z�d�d�Z�e0ej���d%d�d���Z��Z�S(&r:a�
    A multi-level, or hierarchical, index object for pandas objects.

    Parameters
    ----------
    levels : sequence of arrays
        The unique labels for each level.
    codes : sequence of arrays
        Integers for each level designating which label at each location.

        .. versionadded:: 0.24.0
    sortorder : optional int
        Level of sortedness (must be lexicographically sorted by that
        level).
    names : optional sequence of objects
        Names for each of the index levels. (name is accepted for compat).
    copy : bool, default False
        Copy the meta-data.
    verify_integrity : bool, default True
        Check that the levels/codes are consistent and valid.

    Attributes
    ----------
    names
    levels
    codes
    nlevels
    levshape

    Methods
    -------
    from_arrays
    from_tuples
    from_product
    from_frame
    set_levels
    set_codes
    to_frame
    to_flat_index
    is_lexsorted
    sortlevel
    droplevel
    swaplevel
    reorder_levels
    remove_unused_levels
    get_locs

    See Also
    --------
    MultiIndex.from_arrays  : Convert list of arrays to MultiIndex.
    MultiIndex.from_product : Create a MultiIndex from the cartesian product
                              of iterables.
    MultiIndex.from_tuples  : Convert list of tuples to a MultiIndex.
    MultiIndex.from_frame   : Make a MultiIndex from a DataFrame.
    Index : The base pandas Index type.

    Notes
    -----
    See the `user guide
    <https://pandas.pydata.org/pandas-docs/stable/user_guide/advanced.html>`_
    for more.

    Examples
    --------
    A new ``MultiIndex`` is typically constructed using one of the helper
    methods :meth:`MultiIndex.from_arrays`, :meth:`MultiIndex.from_product`
    and :meth:`MultiIndex.from_tuples`. For example (using ``.from_arrays``):

    >>> arrays = [[1, 1, 2, 2], ['red', 'blue', 'red', 'blue']]
    >>> pd.MultiIndex.from_arrays(arrays, names=('number', 'color'))
    MultiIndex([(1,  'red'),
                (1, 'blue'),
                (2,  'red'),
                (2, 'blue')],
               names=['number', 'color'])

    See further examples for how to construct a MultiIndex in the doc strings
    of the mentioned helper methods.
    Z
multiindex�namesNFT)�verify_integrity�
_set_identityc
Cs�|dk	r|}|dks|dkr$td��t|�t|�kr<td��t|�dkrPtd��tjt�}
i|
_|
j||dd�|
j||dd�dgt|�|
_	|dk	r�|
j
|�|dk	r�t|�|
_n||
_|r�|
j
�}||
_|	r�|
j�|
S)NzMust pass both levels and codesz,Length of levels and codes must be the same.rz)Must pass non-zero number of levels/codesF)�copy�validate)�	TypeError�len�
ValueErrorrQ�__new__r:�_cache�_set_levels�
_set_codes�_names�
_set_names�int�	sortorder�_verify_integrity�_codes�_reset_identity)�cls�levelsrErcrT�dtyperW�namerUrV�result�	new_codesrFrFrGr\�s0

zMultiIndex.__new__)�level�codecCs(t|�}tj|�r$tj||d|�}|S)a�
        Reassign code values as -1 if their corresponding levels are NaN.

        Parameters
        ----------
        code : list
            Code to reassign.
        level : list
            Level to check for missing values (NaN, NaT, None).

        Returns
        -------
        new code where code value = -1 if it corresponds
        to a level with missing values (NaN, NaT, None).
        r=���)r+rA�any�where)rDrmrnZ	null_maskrFrFrG�_validate_codes,s
zMultiIndex._validate_codes)rErhc	s^|p�j}|p�j}t|�t|�kr,td��t|d�}x�tt||��D]�\}\}}t|�|krxtddd�|D�����t|�r�|j�t|�kr�td|�d|j��dt|��d	���t|�r�|j�dkr�td|�d|j��d���|jsHtd
t	|��d|����qHW�j
dk	�r:�j
�j�k�r:td�j
�d�j������fdd�t||�D�}t|�}|S)a7
        Parameters
        ----------
        codes : optional list
            Codes to check for validity. Defaults to current codes.
        levels : optional list
            Levels to check for validity. Defaults to current levels.

        Raises
        ------
        ValueError
            If length of levels and codes don't match, if the codes for any
            level would exceed level bounds, or there are any duplicate levels.

        Returns
        -------
        new codes where code value = -1 if it corresponds to a
        NaN level.
        zTLength of levels and codes must match. NOTE: this index is in an inconsistent state.rzUnequal code lengths: cSsg|]}t|��qSrF)rZ)�.0Zcode_rFrFrG�
<listcomp>esz0MultiIndex._verify_integrity.<locals>.<listcomp>z	On level z, code max (z) >= length of level (z/). NOTE: this index is in an inconsistent stater=z, code value (z) < -1zLevel values must be unique: z
 on level NzQValue for sortorder must be inferior or equal to actual lexsort_depth: sortorder z with lexsort_depth csg|]\}}�j||��qSrF)rr)rsrmrn)rDrFrGrt|sro)
rErhrZr[�	enumerate�zip�max�min�	is_unique�listrc�_lexsort_depthr1)rDrErhZcodes_length�irm�level_codesrlrF)rDrGrdAs2

"zMultiIndex._verify_integrity)�returnc	Cs�d}t|�st|��nt|�r&t|�}x|D]}t|�s,t|��q,Wx:tdt|��D](}t||�t||d�krTtd��qTWt|�\}}|tj	kr�dd�|D�}t
||||dd�S)a�
        Convert arrays to MultiIndex.

        Parameters
        ----------
        arrays : list / sequence of array-likes
            Each array-like gives one level's value for each data point.
            len(arrays) is the number of levels.
        sortorder : int or None
            Level of sortedness (must be lexicographically sorted by that
            level).
        names : list / sequence of str, optional
            Names for the levels in the index.

        Returns
        -------
        MultiIndex

        See Also
        --------
        MultiIndex.from_tuples : Convert list of tuples to MultiIndex.
        MultiIndex.from_product : Make a MultiIndex from cartesian product
                                  of iterables.
        MultiIndex.from_frame : Make a MultiIndex from a DataFrame.

        Examples
        --------
        >>> arrays = [[1, 1, 2, 2], ['red', 'blue', 'red', 'blue']]
        >>> pd.MultiIndex.from_arrays(arrays, names=('number', 'color'))
        MultiIndex([(1,  'red'),
                    (1, 'blue'),
                    (2,  'red'),
                    (2, 'blue')],
                   names=['number', 'color'])
        z/Input must be a list / sequence of array-likes.r=zall arrays must be same lengthcSsg|]}t|dd��qS)rjN)�getattr)rsZarrrFrFrGrt�sz*MultiIndex.from_arrays.<locals>.<listcomp>F)rhrErcrTrU)r"rYr!rz�rangerZr[r-r�
no_defaultr:)	rg�arraysrcrTZ	error_msg�arrayr|rErhrFrFrG�from_arrays�s(%


zMultiIndex.from_arrayscCs�t|�std��nt|�r"t|�}t|�dkrN|dkr>td��ggt|�}nVt|tjtf�r�t|t�rn|j	}tt
j|�j�}n$t|t�r�tt
j
|�j�}nt|�}tj|||d�S)a}
        Convert list of tuples to MultiIndex.

        Parameters
        ----------
        tuples : list / sequence of tuple-likes
            Each tuple is the index of one row/column.
        sortorder : int or None
            Level of sortedness (must be lexicographically sorted by that
            level).
        names : list / sequence of str, optional
            Names for the levels in the index.

        Returns
        -------
        MultiIndex

        See Also
        --------
        MultiIndex.from_arrays : Convert list of arrays to MultiIndex.
        MultiIndex.from_product : Make a MultiIndex from cartesian product
                                  of iterables.
        MultiIndex.from_frame : Make a MultiIndex from a DataFrame.

        Examples
        --------
        >>> tuples = [(1, 'red'), (1, 'blue'),
        ...           (2, 'red'), (2, 'blue')]
        >>> pd.MultiIndex.from_tuples(tuples, names=('number', 'color'))
        MultiIndex([(1,  'red'),
                    (1, 'blue'),
                    (2,  'red'),
                    (2, 'blue')],
                   names=['number', 'color'])
        z/Input must be a list / sequence of tuple-likes.rNz-Cannot infer number of levels from empty list)rcrT)r"rYr!rzrZ�
isinstancerA�ndarrayr.�_valuesrZtuples_to_object_array�TZto_object_array_tuplesrvr:r�)rgZtuplesrcrTr�rFrFrG�from_tuples�s %


zMultiIndex.from_tuplescCsjddlm}t|�std��nt|�r.t|�}t|�\}}|tjkrRdd�|D�}||�}t	||||d�S)a�
        Make a MultiIndex from the cartesian product of multiple iterables.

        Parameters
        ----------
        iterables : list / sequence of iterables
            Each iterable has unique labels for each level of the index.
        sortorder : int or None
            Level of sortedness (must be lexicographically sorted by that
            level).
        names : list / sequence of str, optional
            Names for the levels in the index.

            .. versionchanged:: 1.0.0

               If not explicitly provided, names will be inferred from the
               elements of iterables if an element has a name attribute

        Returns
        -------
        MultiIndex

        See Also
        --------
        MultiIndex.from_arrays : Convert list of arrays to MultiIndex.
        MultiIndex.from_tuples : Convert list of tuples to MultiIndex.
        MultiIndex.from_frame : Make a MultiIndex from a DataFrame.

        Examples
        --------
        >>> numbers = [0, 1, 2]
        >>> colors = ['green', 'purple']
        >>> pd.MultiIndex.from_product([numbers, colors],
        ...                            names=['number', 'color'])
        MultiIndex([(0,  'green'),
                    (0, 'purple'),
                    (1,  'green'),
                    (1, 'purple'),
                    (2,  'green'),
                    (2, 'purple')],
                   names=['number', 'color'])
        r)�cartesian_productz-Input must be a list / sequence of iterables.cSsg|]}t|dd��qS)rjN)r)rs�itrFrFrGrt2sz+MultiIndex.from_product.<locals>.<listcomp>)rcrT)
Zpandas.core.reshape.utilr�r"rYr!rzr-rr�r:)rg�	iterablesrcrTr�rErhrFrFrG�from_product�s,

zMultiIndex.from_productcCsBt|t�std��t|j��\}}|dkr.|n|}|j|||d�S)am
        Make a MultiIndex from a DataFrame.

        .. versionadded:: 0.24.0

        Parameters
        ----------
        df : DataFrame
            DataFrame to be converted to MultiIndex.
        sortorder : int, optional
            Level of sortedness (must be lexicographically sorted by that
            level).
        names : list-like, optional
            If no names are provided, use the column names, or tuple of column
            names if the columns is a MultiIndex. If a sequence, overwrite
            names with the given sequence.

        Returns
        -------
        MultiIndex
            The MultiIndex representation of the given DataFrame.

        See Also
        --------
        MultiIndex.from_arrays : Convert list of arrays to MultiIndex.
        MultiIndex.from_tuples : Convert list of tuples to MultiIndex.
        MultiIndex.from_product : Make a MultiIndex from cartesian product
                                  of iterables.

        Examples
        --------
        >>> df = pd.DataFrame([['HI', 'Temp'], ['HI', 'Precip'],
        ...                    ['NJ', 'Temp'], ['NJ', 'Precip']],
        ...                   columns=['a', 'b'])
        >>> df
              a       b
        0    HI    Temp
        1    HI  Precip
        2    NJ    Temp
        3    NJ  Precip

        >>> pd.MultiIndex.from_frame(df)
        MultiIndex([('HI',   'Temp'),
                    ('HI', 'Precip'),
                    ('NJ',   'Temp'),
                    ('NJ', 'Precip')],
                   names=['a', 'b'])

        Using explicit names, instead of the column names

        >>> pd.MultiIndex.from_frame(df, names=['state', 'observation'])
        MultiIndex([('HI',   'Temp'),
                    ('HI', 'Precip'),
                    ('NJ',   'Temp'),
                    ('NJ', 'Precip')],
                   names=['state', 'observation'])
        zInput must be a DataFrameN)rcrT)r�r'rYrv�itemsr�)rgZdfrcrTZcolumn_names�columnsrFrFrG�
from_frame8s
;
zMultiIndex.from_framecCs|jS)N)�values)rDrFrFrGr�|szMultiIndex._valuescCs�|jdk	r|jSg}xjt|j�D]\}|j|�}t|j�r@|j�}t|jt�sZt|t	t
f�rd|jt�}t
j|dd�}|j|�q Wtj|�|_|jS)NF)rW)�_tuplesr��nlevels�_get_level_valuesrriZ_internal_get_valuesr�r&r(r)rRrQrAr��appendrZfast_zip)rDr�r|�valsrFrFrGr��s



zMultiIndex.valuescCstd��dS)z�
        Raises a ValueError for `MultiIndex` because there's no single
        array backing a MultiIndex.

        Raises
        ------
        ValueError
        zcMultiIndex has no single backing array. Use 'MultiIndex.to_numpy()' to get a NumPy array of tuples.N)r[)rDrFrFrGr��s
zMultiIndex.arraycCs
t|�fS)zE
        Return a tuple of the shape of the underlying data.
        )rZ)rDrFrFrG�shape�szMultiIndex.shapecCst|jd�S)Nr)rZrE)rDrFrFrG�__len__�szMultiIndex.__len__cCs4dd�t|j|j�D�}x|D]
}d|_qWt|�S)NcSsg|]\}}|j|d��qS))rj)�
_shallow_copy)rs�xrjrFrFrGrt�sz%MultiIndex.levels.<locals>.<listcomp>T)rv�_levelsr`Z_no_setting_namer1)rDrkrmrFrFrGrh�s

zMultiIndex.levelscs|rVt|�dkrtd��|dkr6t|��jkr6td��|dk	rVt|�t|�krVtd��|dkrvt�fdd�|D��}nP�fdd�|D�}t�j�}x*t||�D]\}}	t|	�d	�j�||<q�Wt|�}|r܈j	|d
�}
|
�_
�j}|�_t|�r��j
|�d�_�j�dS)Nrz#Must set non-zero number of levels.z-Length of levels must match number of levels.z,Length of levels must match length of level.c3s|]}t|�d�j�VqdS))rWN)r0r�)rs�lev)rWrFrG�	<genexpr>�sz)MultiIndex._set_levels.<locals>.<genexpr>csg|]}�j|��qSrF)�_get_level_number)rsr�)rDrFrGrt�sz*MultiIndex._set_levels.<locals>.<listcomp>)rW)rh)rZr[r�r1rzr�rvr0r�rdrerTrprar��_reset_cache)rDrhrmrWrXrU�
new_levels�
level_numbers�lev_numr�rlrTrF)rWrDrGr^�s0

zMultiIndex._set_levelscCs�t|�rt|t�rt|�}|dk	r`t|�r`t|�s>td��t|d�rRtd��|g}|g}n0|dkspt|�r�t|�s�t|d�r�td��|r�|}n|j�}|j�|j||d|d�|s�|SdS)aE

        Set new levels on MultiIndex. Defaults to returning new index.

        Parameters
        ----------
        levels : sequence or list of sequence
            New level(s) to apply.
        level : int, level name, or sequence of int/level names (default None)
            Level(s) to set (None for all levels).
        inplace : bool
            If True, mutates in place.
        verify_integrity : bool, default True
            If True, checks that levels and codes are compatible.

        Returns
        -------
        new index (of same type and class...etc)

        Examples
        --------
        >>> idx = pd.MultiIndex.from_tuples(
        ...     [
        ...         (1, "one"),
        ...         (1, "two"),
        ...         (2, "one"),
        ...         (2, "two"),
        ...         (3, "one"),
        ...         (3, "two")
        ...     ],
        ...     names=["foo", "bar"]
        ... )
        >>> idx
        MultiIndex([(1, 'one'),
            (1, 'two'),
            (2, 'one'),
            (2, 'two'),
            (3, 'one'),
            (3, 'two')],
           names=['foo', 'bar'])

        >>> idx.set_levels([['a', 'b', 'c'], [1, 2]])
        MultiIndex([('a', 1),
                    ('a', 2),
                    ('b', 1),
                    ('b', 2),
                    ('c', 1),
                    ('c', 2)],
                   names=['foo', 'bar'])
        >>> idx.set_levels(['a', 'b', 'c'], level=0)
        MultiIndex([('a', 'one'),
                    ('a', 'two'),
                    ('b', 'one'),
                    ('b', 'two'),
                    ('c', 'one'),
                    ('c', 'two')],
                   names=['foo', 'bar'])
        >>> idx.set_levels(['a', 'b'], level='bar')
        MultiIndex([(1, 'a'),
                    (1, 'b'),
                    (2, 'a'),
                    (2, 'b'),
                    (3, 'a'),
                    (3, 'b')],
                   names=['foo', 'bar'])

        If any of the levels passed to ``set_levels()`` exceeds the
        existing length, all of the values from that argument will
        be stored in the MultiIndex levels, though the values will
        be truncated in the MultiIndex output.

        >>> idx.set_levels([['a', 'b', 'c'], [1, 2, 3, 4]], level=[0, 1])
        MultiIndex([('a', 1),
            ('a', 2),
            ('b', 1),
            ('b', 2),
            ('c', 1),
            ('c', 2)],
           names=['foo', 'bar'])
        >>> idx.set_levels([['a', 'b', 'c'], [1, 2, 3, 4]], level=[0, 1]).levels
        FrozenList([['a', 'b', 'c'], [1, 2, 3, 4]])
        NzLevels must be list-likerz!Levels must be list of lists-likeT)rmrXrU)r"r�r.rzrYr�rfr^)rDrhrm�inplacerU�idxrFrFrG�
set_levels�s(RzMultiIndex.set_levelscCs
t|j�S)z>
        Integer number of levels in this MultiIndex.
        )rZr�)rDrFrFrGr�QszMultiIndex.nlevelscCstdd�|jD��S)z8
        A tuple with the length of each level.
        css|]}t|�VqdS)N)rZ)rsr�rFrFrGr�]sz&MultiIndex.levshape.<locals>.<genexpr>)�tuplerh)rDrFrFrG�levshapeXszMultiIndex.levshapecCs|jS)N)re)rDrFrFrGrEbszMultiIndex.codescs�|rB|dkr"t|��jkr"td��|dk	rBt|�t|�krBtd��|dkrjt�fdd�t�j|�D��}nX�fdd�|D�}t�j�}x2t||�D]$\}}	�j|}
t	|	|
�d�||<q�Wt|�}|r҈j
|d�}|�_d�_�j�dS)	Nz+Length of codes must match number of levelsz,Length of codes must match length of levels.c3s$|]\}}t||�d�j�VqdS))rWN)�_coerce_indexer_frozen�view)rsr�r})rWrFrGr�qsz(MultiIndex._set_codes.<locals>.<genexpr>csg|]}�j|��qSrF)r�)rsr�)rDrFrGrtusz)MultiIndex._set_codes.<locals>.<listcomp>)rW)rE)
rZr�r[r1rvr�rzrerhr�rdr�r�)rDrErmrWrXrUrlr�r�r}r�rF)rWrDrGr_fs(


zMultiIndex._set_codescCs�|dk	rDt|�rDt|�s"td��t|d�r6td��|g}|g}n0|dksTt|�rtt|�slt|d�rttd��|r~|}n|j�}|j�|j|||d�|s�|SdS)a}
        Set new codes on MultiIndex. Defaults to returning new index.

        .. versionadded:: 0.24.0

           New name for deprecated method `set_labels`.

        Parameters
        ----------
        codes : sequence or list of sequence
            New codes to apply.
        level : int, level name, or sequence of int/level names (default None)
            Level(s) to set (None for all levels).
        inplace : bool
            If True, mutates in place.
        verify_integrity : bool (default True)
            If True, checks that levels and codes are compatible.

        Returns
        -------
        new index (of same type and class...etc)

        Examples
        --------
        >>> idx = pd.MultiIndex.from_tuples(
        ...     [(1, "one"), (1, "two"), (2, "one"), (2, "two")], names=["foo", "bar"]
        ... )
        >>> idx
        MultiIndex([(1, 'one'),
            (1, 'two'),
            (2, 'one'),
            (2, 'two')],
           names=['foo', 'bar'])

        >>> idx.set_codes([[1, 0, 1, 0], [0, 0, 1, 1]])
        MultiIndex([(2, 'one'),
                    (1, 'one'),
                    (2, 'two'),
                    (1, 'two')],
                   names=['foo', 'bar'])
        >>> idx.set_codes([1, 0, 1, 0], level=0)
        MultiIndex([(2, 'one'),
                    (1, 'two'),
                    (2, 'one'),
                    (1, 'two')],
                   names=['foo', 'bar'])
        >>> idx.set_codes([0, 0, 1, 1], level='bar')
        MultiIndex([(1, 'one'),
                    (1, 'one'),
                    (2, 'two'),
                    (2, 'two')],
                   names=['foo', 'bar'])
        >>> idx.set_codes([[1, 0, 1, 0], [0, 0, 1, 1]], level=[0, 1])
        MultiIndex([(2, 'one'),
                    (1, 'one'),
                    (2, 'two'),
                    (1, 'two')],
                   names=['foo', 'bar'])
        NzCodes must be list-likerz Codes must be list of lists-like)rmrU)r"rYr�rfr_)rDrErmr�rUr�rFrFrG�	set_codes�s"<zMultiIndex.set_codescCs�tjtjdd�|jD���}tj|ddd��ddd�}tj|dd�dgg�jd�}|ddkrtt|j|j|�St	|j|j|�S)	NcSsg|]}t|�d�qS)r=)rZ)rs�lrFrFrGrt�sz&MultiIndex._engine.<locals>.<listcomp>r=r�uint64�@roro)
rA�ceil�log2rhZcumsum�concatenaterRrPrEr<)rD�sizesZlev_bitsr?rFrFrG�_engine�szMultiIndex._enginecCstjS)N)r:r�)rDrFrFrG�_constructor�szMultiIndex._constructor)rVc	
	Cs�|tjk	r|tjk	rtd��n|tjkr<|tjk	r6|n|j}|dk	rp|dkr\|dkr\|dks`t�tj|||d�S|dk	r||n|j}|dk	r�|n|j}t|||||d|d�}	|j	j
�|	_	|	j	jdd�|	S)Nz*Can only provide one of `names` and `name`)rcrTF)rhrErircrTrUrVrh)rr�rYrT�AssertionErrorr:r�rhrEr]rW�pop)
rDr�rjrhrErircrTrVrkrFrFrGr��s(

zMultiIndex._shallow_copycCs`tj||||�}t|�dkrLtdd�t|j�D�dd�t|j�D�|jd�St|�j||jd�S)NrcSsg|]}g�qSrFrF)rs�_rFrFrGrtsz3MultiIndex.symmetric_difference.<locals>.<listcomp>cSsg|]}g�qSrFrF)rsr�rFrFrGrts)rhrErT)rT)	r.�symmetric_differencerZr:r�r�rj�typer�)rD�otherZresult_name�sortZtupsrFrFrGr�s
zMultiIndex.symmetric_differencec	Cs\|j|||d�}|rDddlm}|dkr2||j�}|dkrD||j�}|j|||||j|d�S)a�
        Make a copy of this object. Names, dtype, levels and codes can be
        passed and will be set on new copy.

        Parameters
        ----------
        names : sequence, optional
        dtype : numpy dtype or pandas type, optional
        levels : sequence, optional
        codes : sequence, optional
        deep : bool, default False
        name : Label
            Kept for compatibility with 1-dimensional Index. Should not be used.

        Returns
        -------
        MultiIndex

        Notes
        -----
        In most cases, there should be no functional difference from using
        ``deep``, but if ``deep`` is passed it will attempt to deepcopy.
        This could be potentially expensive on large MultiIndex objects.
        )rjrT�deepr)�deepcopyN)rhrErTrircrV)Z_validate_namesrWr�rhrEr�rc)	rDrTrirhrEr�rjrVr�rFrFrGrW$s"

zMultiIndex.copycCs|jS)z' the array interface, return my values )r�)rDrirFrFrG�	__array__XszMultiIndex.__array__cCs|j�}|j|_|S)z2 this is defined as a copy with the same identity )rW�_id)rDrgrkrFrFrGr�\szMultiIndex.view)�keyr~c
Cs6t|�y|j|�dStttfk
r0dSXdS)NTF)�hash�get_loc�LookupErrorrYr[)rDr�rFrFrG�__contains__bs
zMultiIndex.__contains__cCs
tjd�S)N�O)rAri)rDrFrFrGrikszMultiIndex.dtypecs dd��t�fdd�|jD��S)z7 return a boolean if we need a qualified .info display cSsd|kpd|kpd|kS)N�mixed�string�unicoderF)r�rFrFrG�frsz0MultiIndex._is_memory_usage_qualified.<locals>.fc3s|]}�|�VqdS)NrF)rsr�)r�rFrGr�usz8MultiIndex._is_memory_usage_qualified.<locals>.<genexpr>)rp�_inferred_type_levels)rDrF)r�rG�_is_memory_usage_qualifiedosz%MultiIndex._is_memory_usage_qualified)r�r~cCs
|j|�S)N)�_nbytes)rDr�rFrFrG�memory_usagewszMultiIndex.memory_usagecCs
|jd�S)z3 return the number of bytes in the underlying data F)r�)rDrFrFrG�nbytes~szMultiIndex.nbytescsjd�t�fdd�|jD��}tdd�|jD��}t�fdd�|jD��}|||}||jj�d�7}|S)z�
        return the number of bytes in the underlying data
        deeply introspect the level data if deep=True

        include the engine hashtable

        *this is in internal routine*

        �c3s|]}|j�d�VqdS))r�N)r�)rsr|)r�rFrGr��sz%MultiIndex._nbytes.<locals>.<genexpr>css|]}|jVqdS)N)r�)rsr|rFrFrGr��sc3s|]}t|��VqdS)N)r)rsr|)�objsizerFrGr��s)r�)�sumrhrErTr��sizeof)rDr�Zlevel_nbytesZlabel_nbytesZnames_nbytesrkrF)r�r�rGr��szMultiIndex._nbytescCs(dd�|jD�}tdd�t||�D��S)zW
        Formats each item in tup according to its level's formatter function.
        cSsg|]
}|j�qSrF)�_formatter_func)rsrmrFrFrGrt�sz.MultiIndex._formatter_func.<locals>.<listcomp>css|]\}}||�VqdS)NrF)rs�func�valrFrFrGr��sz-MultiIndex._formatter_func.<locals>.<genexpr>)rhr�rv)rD�tupZformatter_funcsrFrFrGr��szMultiIndex._formatter_funccCst||j|dd�S)z?
        Return the formatted data as a unicode string
        T)rjZline_break_each_value)r7r�)rDrjrFrFrG�_format_data�szMultiIndex._format_datacCst|dd�S)zH
        Return a list of tuples of the (attr,formatted_value).
        F)Z
include_dtype)r6)rDrFrFrG�
_format_attrs�szMultiIndex._format_attrs�nanc
Ks�g}g}x�t|j|j�D]r\}}|jfd|i|��}|dk}|j�rvt|�}tj||�}|jj	sft
�|j�}|||<|j|�|j|�qWt|�dkr�t|dj
|d��j�St|||j|jdd�}	|	jSdS)N�na_repr=rF)rhrErTrcrUro)rvrhrE�_format_native_typesrprZrAr��flags�	writeabler�rWr.�taker:rTrcr�)
rDr��kwargsr�rlrmr}�maskZ	nan_index�mirFrFrGr��s,
zMultiIndex._format_native_types�)rj�	formatterr�rT�space�adjoinr~cs�|dk	r|}t|�dkrgSg}x�t|j|j�D]�\}	}
|dk	rD|n
t|	jj��t|	�dkr�|	j|
�j|d�}|
dk}|j	�r�t
j|td�}�||<|j
�}n�fdd�tj|	j|
�D�}|j|�q0Wg}
x`t||j�D]P\}	}g}|�r|j|dk	�rt|dd
�nd�|jt
j|	td��|
j|�q�W|dk�r@td�}|�r�d}t|t��sf|tjk�sft�|d
tjgk�rz|}t|
t|�|d�}
|�r�ddlm}|�}|j|f|
��j d	�S|
SdS)Nr)r�r=)rics$g|]}tt|�r�n|dd��qS)�	�
�
)�escape_chars)r�r�r�)r8r+)rsr�)�narFrGrt�sz%MultiIndex.format.<locals>.<listcomp>r�r�r�)r��zdisplay.multi_sparseF)�start�sentinel)�_get_adjustmentro)r�r�r�)!rZrvrhrE�_get_na_reprir�r��formatrprAr�rQ�tolistr�take_1dr�r�rTr8�extendr
r��boolrr�r��	_sparsifyrbZpandas.io.formats.formatr�r��split)rDrjr�r�rTr�Zsparsifyr�Zstringified_levelsr�r}�	formattedr�Z
result_levelsZlev_namermr�r�ZadjrF)r�rGr��sP



zMultiIndex.formatcCs
t|j�S)N)r1r`)rDrFrFrG�
_get_namesszMultiIndex._get_namescs�|dk	rt|�rtd��t|�}|rd|dk	rFt|�t|�krFtd��|dkrdt|��jkrdtd��|dkrxt�j�}n�fdd�|D�}xDt||�D]6\}}|dk	r�t|�s�tt	��j
�d���|�j|<q�W�j�dS)a�
        Set new names on index. Each name has to be a hashable type.

        Parameters
        ----------
        values : str or sequence
            name(s) to set
        level : int, level name, or sequence of int/level names (default None)
            If the index is a MultiIndex (hierarchical), level(s) to set (None
            for all levels).  Otherwise level must be None
        validate : boolean, default True
            validate that the names match level lengths

        Raises
        ------
        TypeError if each name is not hashable.

        Notes
        -----
        sets names on levels. WARNING: mutates!

        Note that you generally want to set this *after* changing levels, so
        that it only acts on copies
        Nz*Names should be list-like for a MultiIndexz+Length of names must match length of level.z:Length of names must match number of levels in MultiIndex.csg|]}�j|��qSrF)r�)rsr�)rDrFrGrtLsz)MultiIndex._set_names.<locals>.<listcomp>z.name must be a hashable type)
r"r[rzrZr�r�rvrrYr�rIr`r�)rDrTrmrXr�rjrF)rDrGra"s&zMultiIndex._set_namesz 
Names of levels in MultiIndex.
)�fset�fgetrcCs�|j|}|j|}|dk	r@|j|j|�}|j|�}|ddfStj|dd�\}}t|�dkr�|ddkr�|dk}	tj||	dd�\}
}tjt|�|j	d�}|
||	<d	||	<t|�t|�kr�|j|�}n|j
�}|jr�|j|dd�}n
|j|�}|||fS)
NT)r�rr=)ri)�
fill_valuerororo)rErhr��maprZ	factorizerZrA�emptyrirWZ_can_hold_na)rD�mapperrm�indexer�level_indexZlevel_valuesZgrouperrE�uniquesr�Zok_codesrFrFrG�_get_grouper_for_levelbs(





z!MultiIndex._get_grouper_for_levelcCsdS)Nr�rF)rDrFrFrG�
inferred_type�szMultiIndex.inferred_typecCs�|jj|�}|dkr.t|�r.td|�d���y|jj|�}Wn�tk
r�}z�t|�sltd|�d��|�nf|dkr�||j7}|dkr�||j}td|j�d|�d	��|�n&||jkr�td|j�d
|d���|�WYdd}~XnX|S)Nr=z	The name z* occurs multiple times, use a level numberzLevel z
 not foundrz Too many levels: Index has only z	 levels, z is not a valid level numberz
 levels, not )rT�countr r[r�KeyErrorr��
IndexError)rDrmr�errZ
orig_levelrFrFrGr��s*


zMultiIndex._get_level_numbercCsdS)NTrF)rDrFrFrG�_has_complex_internals�sz!MultiIndex._has_complex_internalscs�tdd��jD��rdStdd��jD��rBtjdd��jD��S�fdd�ttt�j���D�}yt	j
|�}t|�jSt
k
r�t�j�jSXdS)	zh
        return if the index is monotonic increasing (only equal or
        increasing) values.
        css|]}d|kVqdS)r=NrorF)rsrnrFrFrGr��sz5MultiIndex.is_monotonic_increasing.<locals>.<genexpr>Fcss|]}|jVqdS)N)�is_monotonic)rsrmrFrFrGr��scSsg|]}|jddd��qS)�int64F)rW)rR)rsr�rFrFrGrt�sz6MultiIndex.is_monotonic_increasing.<locals>.<listcomp>csg|]}�j|�j�qSrF)r�r�)rsr|)rDrFrGrt�sN)rprE�allrh�libalgos�is_lexsorted�reversedr�rZrA�lexsortr.rrYr�)rDr�Z
sort_orderrF)rDrG�is_monotonic_increasing�s 

z"MultiIndex.is_monotonic_increasingcCs|ddd�jS)zh
        return if the index is monotonic decreasing (only equal or
        decreasing) values.
        Nr=ro)r)rDrFrFrG�is_monotonic_decreasing�sz"MultiIndex.is_monotonic_decreasingcCsdd�|jD�S)z9 return a list of the inferred types, one for each level cSsg|]
}|j�qSrF)r)rsr|rFrFrGrt�sz4MultiIndex._inferred_type_levels.<locals>.<listcomp>)rh)rDrFrFrGr��sz MultiIndex._inferred_type_levels�firstcCs(tt|j�}t|j|ddd�}t||�S)NF)r�Zxnull)r�rZrhr3rEr)rDZkeepr��idsrFrFrG�
duplicated�szMultiIndex.duplicatedcCstd��dS)z:
        fillna is not implemented for MultiIndex
        z"isna is not defined for MultiIndexN)�NotImplementedError)rD�valueZdowncastrFrFrG�fillna�szMultiIndex.fillnarpcspdd�|jD�}|dkr(tj|dd��n&|dkr@tj|dd��ntd|�����fdd�|jD�}|j|d	d
�S)NcSsg|]}|dk�qS)r=rorF)rsr}rFrFrGrt�sz%MultiIndex.dropna.<locals>.<listcomp>rpr)r>r
zinvalid how option: csg|]}|��qSrFrF)rsr})r�rFrGrt�sT)rEr�)rErArpr
r[rW)rD�howZnansrlrF)r�rG�dropna�szMultiIndex.dropnacCsN|j|}|j|}|j|}|r,tj|�}tj|j||jd�}|j||d�S)aa
        Return vector of label values for requested level,
        equal to the length of the index

        **this is an internal method**

        Parameters
        ----------
        level : int level
        unique : bool, default False
            if True, drop duplicated values

        Returns
        -------
        values : ndarray
        )r�)rj)	rhrEr`r�uniquer�r�Z	_na_valuer�)rDrmrr�r}rjZfilledrFrFrGr��s



zMultiIndex._get_level_valuescCs|j|�}|j|�}|S)a�
        Return vector of label values for requested level.

        Length of returned vector is equal to the length of the index.

        Parameters
        ----------
        level : int or str
            ``level`` is either the integer position of the level in the
            MultiIndex, or the name of the level.

        Returns
        -------
        values : Index
            Values is a level of this MultiIndex converted to
            a single :class:`Index` (or subclass thereof).

        Examples
        --------
        Create a MultiIndex:

        >>> mi = pd.MultiIndex.from_arrays((list('abc'), list('def')))
        >>> mi.names = ['level_1', 'level_2']

        Get level values by supplying level as either integer or name:

        >>> mi.get_level_values(0)
        Index(['a', 'b', 'c'], dtype='object', name='level_1')
        >>> mi.get_level_values('level_2')
        Index(['d', 'e', 'f'], dtype='object', name='level_2')
        )r�r�)rDrmr�rFrFrG�get_level_valuess 

zMultiIndex.get_level_valuescs.|dkrt�j�S|j|�}|j|dd�SdS)NT)rmr)�superrr�r�)rDrm)�	__class__rFrGr+s

zMultiIndex.uniquecCs|jdd�|jD��S)z+ convert to object if we are a categorical cSsg|]}|j��qSrF)�_to_safe_for_reshape)rsr|rFrFrGrt6sz3MultiIndex._to_safe_for_reshape.<locals>.<listcomp>)r�rh)rDrFrFrGr4szMultiIndex._to_safe_for_reshapecs�ddlm}|dk	rDt|�s$td��t|�t�j�kr>td��|}n�j}|�fdd�t|t	t�j���D�dd	�}|r~�|_
|S)
a�
        Create a DataFrame with the levels of the MultiIndex as columns.

        Column ordering is determined by the DataFrame constructor with data as
        a dict.

        .. versionadded:: 0.24.0

        Parameters
        ----------
        index : bool, default True
            Set the index of the returned DataFrame as the original MultiIndex.

        name : list / sequence of str, optional
            The passed names should substitute index level names.

        Returns
        -------
        DataFrame : a DataFrame containing the original MultiIndex data.

        See Also
        --------
        DataFrame : Two-dimensional, size-mutable, potentially heterogeneous
            tabular data.
        r)�	DataFrameNz1'name' must be a list / sequence of column names.z<'name' should have same length as number of levels on index.cs(i|] \}}�j|�|dkr |n|�qS)N)r�)rsZlvlnamerm)rDrFrG�
<dictcomp>bsz'MultiIndex.to_frame.<locals>.<dictcomp>F)rW)�pandasrr"rYrZrhr[rTrvr�r)rDrrjrZ	idx_namesrkrF)rDrG�to_frame8s 
zMultiIndex.to_framecCst|jdd�S)a�
        Convert a MultiIndex to an Index of Tuples containing the level values.

        .. versionadded:: 0.24.0

        Returns
        -------
        pd.Index
            Index with the MultiIndex data represented in Tuples.

        Notes
        -----
        This method will simply return the caller if called by anything other
        than a MultiIndex.

        Examples
        --------
        >>> index = pd.MultiIndex.from_product(
        ...     [['foo', 'bar'], ['baz', 'qux']],
        ...     names=['a', 'b'])
        >>> index.to_flat_index()
        Index([('foo', 'baz'), ('foo', 'qux'),
               ('bar', 'baz'), ('bar', 'qux')],
              dtype='object')
        F)Z
tupleize_cols)r.r�)rDrFrFrG�
to_flat_indexmszMultiIndex.to_flat_indexcCsdS)NFrF)rDrFrFrG�is_all_dates�szMultiIndex.is_all_datescCs|j|jkS)a`
        Return True if the codes are lexicographically sorted.

        Returns
        -------
        bool

        Examples
        --------
        In the below examples, the first level of the MultiIndex is sorted because
        a<b<c, so there is no need to look at the next level.

        >>> pd.MultiIndex.from_arrays([['a', 'b', 'c'], ['d', 'e', 'f']]).is_lexsorted()
        True
        >>> pd.MultiIndex.from_arrays([['a', 'b', 'c'], ['d', 'f', 'e']]).is_lexsorted()
        True

        In case there is a tie, the lexicographical sorting looks
        at the next level of the MultiIndex.

        >>> pd.MultiIndex.from_arrays([[0, 1, 1], ['a', 'b', 'c']]).is_lexsorted()
        True
        >>> pd.MultiIndex.from_arrays([[0, 1, 1], ['a', 'c', 'b']]).is_lexsorted()
        False
        >>> pd.MultiIndex.from_arrays([['a', 'a', 'b', 'b'],
        ...                            ['aa', 'bb', 'aa', 'bb']]).is_lexsorted()
        True
        >>> pd.MultiIndex.from_arrays([['a', 'a', 'b', 'b'],
        ...                            ['bb', 'aa', 'aa', 'bb']]).is_lexsorted()
        False
        )�
lexsort_depthr�)rDrFrFrGr�s zMultiIndex.is_lexsortedcCs|jdk	r|jS|j�S)N)rcr{)rDrFrFrGr$�s
zMultiIndex.lexsort_depthcCsBdd�|jD�}x,t|jdd�D]}tj|d|��r |Sq WdS)z�
        Compute and return the lexsort_depth, the number of levels of the
        MultiIndex that are sorted lexically

        Returns
        -------
        int
        cSsg|]}t|��qSrF)r)rsr}rFrFrGrt�sz-MultiIndex._lexsort_depth.<locals>.<listcomp>rr=Nro)rEr�r�rr)rDZint64_codes�krFrFrGr{�s
	zMultiIndex._lexsort_depthc
Cs�|j�r|jr|Sg}g}x�t|j|j�D]r\}}|js�y|j�}Wntk
rXYn0X|j|�}t|�}t	j
|t|��}tj
||�}|j|�|j|�q*Wt|||j|jdd�S)a�
        This is an *internal* function.

        Create a new MultiIndex from the current to monotonically sorted
        items IN the levels. This does not actually make the entire MultiIndex
        monotonic, JUST the levels.

        The resulting MultiIndex will have the same outward
        appearance, meaning the same .values and ordering. It will also
        be .equals() to the original.

        Returns
        -------
        MultiIndex

        Examples
        --------
        >>> mi = pd.MultiIndex(levels=[['a', 'b'], ['bb', 'aa']],
        ...                    codes=[[0, 0, 1, 1], [0, 1, 0, 1]])
        >>> mi
        MultiIndex([('a', 'bb'),
                    ('a', 'aa'),
                    ('b', 'bb'),
                    ('b', 'aa')],
                   )

        >>> mi.sort_values()
        MultiIndex([('a', 'aa'),
                    ('a', 'bb'),
                    ('b', 'aa'),
                    ('b', 'bb')],
                   )
        F)rTrcrU)rrrvrhrE�argsortrYr�rrZget_reverse_indexerrZrr�r�r:rTrc)rDr�rlr�r}r��rirFrFrG�_sort_levels_monotonic�s,"

z!MultiIndex._sort_levels_monotoniccCsBg}g}d}�x�t|j|j�D]�\}}tjtj|d�dk�dd}tt|�oZ|ddk�}t|�t|�|kr�d}tj	|�}|r�tj|dk�d}||ddg|d|dg<tj
t|�|�}	tjt|��||	|<|	|}|j||d��}|j
|�|j
|�qW|j�}
|�r>|
j�|
j|dd�|
j|dd�|
S)	a�
        Create new MultiIndex from current that removes unused levels.

        Unused level(s) means levels that are not expressed in the
        labels. The resulting MultiIndex will have the same outward
        appearance, meaning the same .values and ordering. It will
        also be .equals() to the original.

        Returns
        -------
        MultiIndex

        Examples
        --------
        >>> mi = pd.MultiIndex.from_product([range(2), list('ab')])
        >>> mi
        MultiIndex([(0, 'a'),
                    (0, 'b'),
                    (1, 'a'),
                    (1, 'b')],
                   )

        >>> mi[2:]
        MultiIndex([(1, 'a'),
                    (1, 'b')],
                   )

        The 0 from the first level is not represented
        and can be removed

        >>> mi2 = mi[2:].remove_unused_levels()
        >>> mi2.levels
        FrozenList([[1], ['a', 'b']])
        Fr=rTN)rXroro)rvrhrErArqZbincountrbrZrr�zeros�aranger�r�r�rfr^r_)rDr�rl�changedr�r}rZhas_naZna_idxZcode_mappingrkrFrFrG�remove_unused_levelss0# 

zMultiIndex.remove_unused_levelscCs8tt|j�t|j�|jt|j�d�}tjt|�|fdfS)z*Necessary for making this object picklable)rhrErcrTN)	�dictrzrhrErcrT�ibaseZ
_new_Indexr�)rD�drFrFrG�
__reduce___szMultiIndex.__reduce__cs�t��rjtj�dd��g}xFt|j|j�D]4\}}|�d	krL|jtj�q*|j||��q*Wt	|�Stj
��r�tj�td��|j
}nd}t�t�r�tj����fdd�|jD�}t|j||j|dd�SdS)
NT)Z
warn_floatr=)ricsg|]}|��qSrFrF)rsr})r�rFrGrt�sz*MultiIndex.__getitem__.<locals>.<listcomp>F)rhrErTrcrUro)r$�comZcast_scalar_indexerrvrhrEr�rAr�r��is_bool_indexer�asarrayr�rcr�r.r:rT)rDr��retvalr�r}rcrlrF)r�rG�__getitem__ks*


zMultiIndex.__getitem__r�rcKs@tjt�|�t|�}|j|j|||dd�}t|j||jdd�S)Nr=)�
allow_fillr��na_valueF)rhrErTrUro)	�nvZ
validate_taker�r�_assert_take_fillablerEr:rhrT)rD�indicesr>r6r�r��takenrFrFrGr��szMultiIndex.takecs�|r||dk	r|�dkj�r$d}t|���fdd�|jD�}�dk}|j�r�g}	x(|D] }
|
}|||<|	jtj|��qRW|	}n�fdd�|jD�}|S)	z. Internal method to handle NA filling of take Nr=zJWhen allow_fill=True and fill_value is not None, all indices must be >= -1csg|]}|j���qSrF)r�)rs�lab)r:rFrGrt�sz4MultiIndex._assert_take_fillable.<locals>.<listcomp>csg|]}|j���qSrF)r�)rsr<)r:rFrGrt�sroro)rpr[rEr�rAr3)rDr�r:r6r�r7�msgr;r�ZmaskedZ	new_labelZlabel_valuesrF)r:rGr9�s
z MultiIndex._assert_take_fillablecs�t|ttf�s|g}t�fdd�|D��r~g}x>t�j�D]0��j��}�fdd�|D�}|j|j|��q:Wtj	|�j
d�S�jftdd�|D��}tj
|�}ytj|�j
d�Sttfk
r�t|�SXdS)z�
        Append a collection of Index options together

        Parameters
        ----------
        other : Index or list/tuple of indices

        Returns
        -------
        appended : Index
        c3s$|]}t|t�o|j�jkVqdS)N)r�r:r�)rs�o)rDrFrGr��sz$MultiIndex.append.<locals>.<genexpr>csg|]}|j���qSrF)r�)rsr>)r|rFrGrt�sz%MultiIndex.append.<locals>.<listcomp>)rTcss|]}|jVqdS)N)r�)rsr%rFrFrGr��sN)r�rzr�r
r�r�r�r�r:r�rTr�rAr�r�rYrr.)rDr�r��labelZappendedZ	to_concatZ
new_tuplesrF)r|rDrGr��s 

zMultiIndex.appendcOs|jj||�S)N)r�r&)rD�argsr�rFrFrGr&�szMultiIndex.argsort�repeatcsDtjt�t|d��t���t|j�fdd�|jD�|j|j	dd�S)N)r>cs&g|]}|jtj�jtj�j���qSrF)r�rAr�rR�intprA)rsr})�repeatsrFrGrt�sz%MultiIndex.repeat.<locals>.<listcomp>F)rhrErTrcrU)
r8Zvalidate_repeatr�r-rr:rhrErTrc)rDrCr>rF)rCrGrA�s
zMultiIndex.repeatcCstd��dS)Nz1.where is not supported for MultiIndex operations)r)rDZcondr�rFrFrGrq�szMultiIndex.where�raisecCs$|dk	r|j|||�St|tjtf�sNytj|td�}Wntk
rLYnXg}x�|D]�}y�|j	|�}t|t
�r~|j|�nrt|t�r�|j
t|j|j��nRtj|�r�|jdkr�tjdtdd�|j�d}|j
|�ndt|���}t|��WqXtk
�r|dk�r�YqXXqXW|j|�S)	aB
        Make new MultiIndex with passed list of codes deleted

        Parameters
        ----------
        codes : array-like
            Must be a list of tuples
        level : int or level name, default None
        errors : str, default 'raise'

        Returns
        -------
        dropped : MultiIndex
        N)rirzYdropping on a non-lexsorted multi-index without a level parameter may impact performance.�)�
stacklevelzunsupported indexer of type �ignore)�_drop_from_levelr�rAr�r.r1�index_labels_to_arrayrQr[r�rbr��slicer�r�r��stopr2r$�warnings�warnr�nonzeror�r�r�delete)rDrErm�errorsZindsr}�locr=rFrFrG�drop�s:






zMultiIndex.dropcCsdtj|�}|j|�}|j|}|j|�}tj|j||�}|j�r\|dkr\t	d|�d���||S)NrGzlabels z not found in level)
r1rIr�rh�get_indexerr�isinrEr
r)rDrErmrPr|rr�r�rFrFrGrH s



zMultiIndex._drop_from_levelr=cCs�t|j�}t|j�}t|j�}|j|�}|j|�}||||||<||<||||||<||<||||||<||<t|||dd�S)a�
        Swap level i with level j.

        Calling this method does not change the ordering of the values.

        Parameters
        ----------
        i : int, str, default -2
            First level of index to be swapped. Can pass level name as string.
            Type of parameters can be mixed.
        j : int, str, default -1
            Second level of index to be swapped. Can pass level name as string.
            Type of parameters can be mixed.

        Returns
        -------
        MultiIndex
            A new MultiIndex.

        See Also
        --------
        Series.swaplevel : Swap levels i and j in a MultiIndex.
        Dataframe.swaplevel : Swap levels i and j in a MultiIndex on a
            particular axis.

        Examples
        --------
        >>> mi = pd.MultiIndex(levels=[['a', 'b'], ['bb', 'aa']],
        ...                    codes=[[0, 0, 1, 1], [0, 1, 0, 1]])
        >>> mi
        MultiIndex([('a', 'bb'),
                    ('a', 'aa'),
                    ('b', 'bb'),
                    ('b', 'aa')],
                   )
        >>> mi.swaplevel(0, 1)
        MultiIndex([('bb', 'a'),
                    ('aa', 'a'),
                    ('bb', 'b'),
                    ('aa', 'b')],
                   )
        F)rhrErTrU)rzrhrErTr�r:)rDr|�jr�rl�	new_namesrFrFrG�	swaplevel,s+




zMultiIndex.swaplevelcs��fdd�|D�}t|��jkr:td�j�dt|������fdd�|D�}�fdd�|D�}�fdd�|D�}t|||dd	�S)
aP
        Rearrange levels using input order. May not drop or duplicate levels.

        Parameters
        ----------
        order : list of int or list of str
            List representing new level order. Reference level by number
            (position) or by key (label).

        Returns
        -------
        MultiIndex
        csg|]}�j|��qSrF)r�)rsr|)rDrFrGrttsz-MultiIndex.reorder_levels.<locals>.<listcomp>z2Length of order must be same as number of levels (z), got csg|]}�j|�qSrF)rh)rsr|)rDrFrGrtzscsg|]}�j|�qSrF)rE)rsr|)rDrFrGrt{scsg|]}�j|�qSrF)rT)rsr|)rDrFrGrt|sF)rhrErTrU)rZr�r�r:)rD�orderr�rlrVrF)rDrG�reorder_levelsfszMultiIndex.reorder_levelscsdd���fdd�|jD�S)a
        we categorizing our codes by using the
        available categories (all, not just observed)
        excluding any missing ones (-1); this is in preparation
        for sorting, where we need to disambiguate that -1 is not
        a valid valid
        cSs*tjt|�rtj|�j�dnd|jd�S)Nr=r)ri)rAr*rZr�rwri)r}rFrFrG�cats�sz/MultiIndex._get_codes_for_sorting.<locals>.catscs g|]}tj|�|�dd��qS)T)�ordered)r,Z
from_codes)rsr})rZrFrGrt�sz5MultiIndex._get_codes_for_sorting.<locals>.<listcomp>)rE)rDrF)rZrG�_get_codes_for_sorting�s	
z!MultiIndex._get_codes_for_sortingc
s\t|ttf�r|g}�fdd�|D�}d}t|t�rht|�t|�ksLtd��t�fdd�|D�|d��n�t�j��t�j��t	�fdd�|D��}t	�fd	d�|D��}x(t
|d
d�D]}�j|��j|�q�W|r�||t	��7}||t	��7}n|d}t||d
d��|�s"�ddd��t
����fdd��jD�}t|�j�j|d
d�}	|	�fS)a
        Sort MultiIndex at the requested level.

        The result will respect the original ordering of the associated
        factor at that level.

        Parameters
        ----------
        level : list-like, int or str, default 0
            If a string is given, must be a name of the level.
            If list-like must be names or ints of levels.
        ascending : bool, default True
            False to sort in descending order.
            Can also be a list to specify a directed ordering.
        sort_remaining : sort by the remaining levels after level

        Returns
        -------
        sorted_index : pd.MultiIndex
            Resulting index.
        indexer : np.ndarray
            Indices of output values in original index.
        csg|]}�j|��qSrF)r�)rsr�)rDrFrGrt�sz(MultiIndex.sortlevel.<locals>.<listcomp>Nz(level must have same length as ascendingcsg|]}�j|�qSrF)rE)rsr�)rDrFrGrt�s)Zordersc3s|]}�|VqdS)NrF)rsr�)rErFrGr��sz'MultiIndex.sortlevel.<locals>.<genexpr>c3s|]}�|VqdS)NrF)rsr�)r�rFrGr��sT)�reverserF)�compressr=csg|]}|j���qSrF)r�)rsr})r�rFrGrt�s)rErhrTrcrUro)r��strrbrzrZr[r5rEr�r��sortedr�r4rr:rhrT)
rDrmZ	ascendingZsort_remainingrcZprimaryZprimshpr�rl�	new_indexrF)rEr�rDr�rG�	sortlevel�s@



zMultiIndex.sortlevelcCs^t|d�}|dk	r�|dk	r$td��tj|�}t|�dkr�t|t�r�|j|}|j�}|j	dd�t
|�jtj
d|jd�f|�}nt|�}|j||ddd	d
�\}}	}
n:t|�}|j|�r�d}	n"|jr�|j||||d�}	ntd��t|t��s |	dkr�|}n$|	dkj��r|j|	�}n
tj|�}|�rV|j|jk�rV|j|jk�rV|jd	d
�}|j|_||	fS)a
        Create index with target's values (move/add/delete values as necessary)

        Returns
        -------
        new_index : pd.MultiIndex
            Resulting index
        indexer : np.ndarray or None
            Indices of output values in original index.

        rTNz)Fill method not supported if level passedr�freq)ri�rightTF)rZreturn_indexersZ
keep_order)�method�limit�	tolerancez'cannot handle a non-unique multi-index!)r�)�hasattrrYr.Zensure_has_lenrZr�r.rhZ_get_attributes_dictr�r�Z_simple_newrAr�rir0Z_join_level�equalsryrSr[r:r
r�r�r�rTrW)rD�targetrermrfrgZpreserve_namesr��attrsr�r�rFrFrG�reindex�s@

 

zMultiIndex.reindexcCst|�st|�rt|��dS)N)rr!r)rDr�rFrFrG�_check_indexing_error'	sz MultiIndex._check_indexing_errorcCs|jdj�S)zA
        Should integer key(s) be treated as positional?
        r)rh�_should_fallback_to_positional)rDrFrFrGrn.	sz)MultiIndex._should_fallback_to_positionalr9)�seriescCsD|j|}t|�r|S||}t||�}|j|||jd�}|j|�S)z�
        Do a positional lookup on the given Series, returning either a scalar
        or a Series.

        Assumes that `series.index is self`
        )rrj)r�r$�maybe_droplevelsr�rjZ__finalize__)rDrorQr�Z
new_valuesraZnew_serrFrFrG�_get_values_for_loc5	s

zMultiIndex._get_values_for_loccs�t�j|�\}}|dkr�t|�r�t|dt�r�d}|j||d�\}}|dkr\tjt|��}|jdj	|�}|dk}|j
�r�t||�d���||fS)a
        Parameters
        ----------
        keyarr : list-like
            Indexer to convert.

        Returns
        -------
        tuple (indexer, keyarr)
            indexer is an ndarray or None if cannot convert
            keyarr are tuple-safe keys
        Nr)rmr=z
 not in indexro)r�_convert_listlike_indexerrZr�r�rlrAr*rhrSrpr)rDZkeyarrr�rmr��checkr�)rrFrGrrE	s
 z$MultiIndex._convert_listlike_indexercCs�t|t�r8|jdjr8t|gtd�gt|j�d�}t|t�r�g}xHt|�D]<\}}t|t�r�|j|jr�|jt||d��qP|j|�qPWt|�}|S)z�
        Translate any partial string timestamp matches in key, returning the
        new key.

        Only relevant for MultiIndex.
        rNr=)	r�r_rhZ!_supports_partial_string_indexingr�rJrZrur�)rDr�Znew_keyr|�	componentrFrFrG�'_get_partial_string_timestamp_match_keyd	s"

z2MultiIndex._get_partial_string_timestamp_match_keyrScCs�tj|�}t|�}t|�r2t|�r2ttjg��St|t	�s�yt	j
|�}Wn8ttfk
r�|dkr~t
|j�j||||d�SYnX|js�td��|dks�|dkr�|dk	r�td��|jj|j|||d�}n|dkr�td��n|jj|�}t|�S)	N)rerfrgz8Reindexing only valid with uniquely valued Index objects�padZbackfillz,tolerance not implemented yet for MultiIndex)r�rjrerfZnearestzJmethod='nearest' not implemented yet for MultiIndex; see GitHub issue 9365)�missingZclean_reindex_fill_methodr0r"rZrrAr�r�r:r�rYr[r.r�rSryrr�)rDrjrerfrgr�rFrFrGrS�	s0


zMultiIndex.get_indexer�get_indexer_non_uniquecst�j|�S)N)rrx)rDrj)rrFrGrx�	sz!MultiIndex.get_indexer_non_unique)r?�side�kindr~cCst|t�s|f}|j||d�S)a�
        For an ordered MultiIndex, compute slice bound
        that corresponds to given label.

        Returns leftmost (one-past-the-rightmost if `side=='right') position
        of given label.

        Parameters
        ----------
        label : object or tuple of objects
        side : {'left', 'right'}
        kind : {'loc', 'getitem'}

        Returns
        -------
        int
            Index of label.

        Notes
        -----
        This method only works if level 0 index of the MultiIndex is lexsorted.

        Examples
        --------
        >>> mi = pd.MultiIndex.from_arrays([list('abbc'), list('gefd')])

        Get the locations from the leftmost 'b' in the first level
        until the end of the multiindex:

        >>> mi.get_slice_bound('b', side="left", kind="loc")
        1

        Like above, but if you get the locations from the rightmost
        'b' in the first level and 'f' in the second level:

        >>> mi.get_slice_bound(('b','f'), side="right", kind="loc")
        3

        See Also
        --------
        MultiIndex.get_loc : Get location for a label or a tuple of labels.
        MultiIndex.get_locs : Get location for a label/slice/list/mask or a
                              sequence of such.
        )ry)r�r��_partial_tup_index)rDr?ryrzrFrFrG�get_slice_bound�	s/
zMultiIndex.get_slice_boundcst�j||||d�S)a{
        For an ordered MultiIndex, compute the slice locations for input
        labels.

        The input labels can be tuples representing partial levels, e.g. for a
        MultiIndex with 3 levels, you can pass a single value (corresponding to
        the first level), or a 1-, 2-, or 3-tuple.

        Parameters
        ----------
        start : label or tuple, default None
            If None, defaults to the beginning
        end : label or tuple
            If None, defaults to the end
        step : int or None
            Slice step
        kind : string, optional, defaults None

        Returns
        -------
        (start, end) : (int, int)

        Notes
        -----
        This method only works if the MultiIndex is properly lexsorted. So,
        if only the first 2 levels of a 3-level MultiIndex are lexsorted,
        you can only pass two levels to ``.slice_locs``.

        Examples
        --------
        >>> mi = pd.MultiIndex.from_arrays([list('abbd'), list('deff')],
        ...                                names=['A', 'B'])

        Get the slice locations from the beginning of 'b' in the first level
        until the end of the multiindex:

        >>> mi.slice_locs(start='b')
        (1, 4)

        Like above, but stop at the end of 'b' in the first level and 'f' in
        the second level:

        >>> mi.slice_locs(start='b', end=('b', 'f'))
        (1, 3)

        See Also
        --------
        MultiIndex.get_loc : Get location for a label or a tuple of labels.
        MultiIndex.get_locs : Get location for a label/slice/list/mask or a
                              sequence of such.
        )rz)r�
slice_locs)rDr��end�steprz)rrFrGr}�	s6zMultiIndex.slice_locs�leftcCs<t|�|jkr*tdt|��d|j�d���t|�}dt|�}}t||j|j�}x�t|�D]�\}\}}	}
|
||�}||	kr�t|�r�|	jt	j
|gdd��s�td|����|	j||d�}|d	kr�|dkr�|d
8}||j||d�S|j
|	|�}
||d
k�r"||j|
d	d�}||j|
dd�}qZ||j|
|d�SqZWdS)NzKey length (z-) was greater than MultiIndex lexsort depth (�)rF)ZskipnazLevel type mismatch: )ryrdr=r�)rZr$rrvrhrErur+Zis_type_compatiblerZinfer_dtyperY�searchsorted�_get_loc_single_level_index)rDr�ry�nr�r~Zzippedr%r<r�Zlabs�sectionrQr�rFrFrGr{
s(zMultiIndex._partial_tup_index)r�r�r~cCs"t|�rt|�rdS|j|�SdS)a�
        If key is NA value, location of index unify as -1.

        Parameters
        ----------
        level_index: Index
        key : label

        Returns
        -------
        loc : int
            If key is NA value, loc is -1
            Else, location of key in index.

        See Also
        --------
        Index.get_loc : The get_loc method for (single-level) index.
        r=Nro)r$r+r�)rDr�r�rFrFrGr�7
sz&MultiIndex._get_loc_single_level_indexc
s�|dk	rtd��t|��fdd�}t|t�sD�j|dd�}||�St|�}�j|krntd|�d�j�d	���|�jkr��jr��j	j
|�S�j}|d|�||d�}}|r��j||�n
dt��f\}	}
|	|
kr�t|��|s�t
|	|
�Stjd
tdd�tj|	|
tjd
�}x`t|t|��D]N\}}�j||�j�j||�k}|j��sT||}t|��st|���qWt|�|
|	k�r�||�St
|	|
�S)a�
        Get location for a label or a tuple of labels.

        The location is returned as an integer/slice or boolean
        mask.

        Parameters
        ----------
        key : label or tuple of labels (one for each level)
        method : None

        Returns
        -------
        loc : int, slice object or boolean mask
            If the key is past the lexsort depth, the return may be a
            boolean mask array, otherwise it is always a slice or int.

        See Also
        --------
        Index.get_loc : The get_loc method for (single-level) index.
        MultiIndex.slice_locs : Get slice location given start label(s) and
                                end label(s).
        MultiIndex.get_locs : Get location for a label/slice/list/mask or a
                              sequence of such.

        Notes
        -----
        The key cannot be a slice, list of same-level labels, a boolean mask,
        or a sequence of such. If you want to use those, use
        :meth:`MultiIndex.get_locs` instead.

        Examples
        --------
        >>> mi = pd.MultiIndex.from_arrays([list('abb'), list('def')])

        >>> mi.get_loc('b')
        slice(1, 3, None)

        >>> mi.get_loc(('b', 'e'))
        1
        NzEonly the default get_loc method is currently supported for MultiIndexcsdt|tj�s|jtjkr|Stj|t���}t|t�r<|Stj	t��dd�}|j
d�d||<|S)z<convert integer indexer to boolean mask or slice if possibler�)riFT)r�rAr�rirBrZmaybe_indices_to_slicerZrJr��fill)rQr�)rDrFrG�_maybe_to_slice�
s

z+MultiIndex.get_loc.<locals>._maybe_to_slicer)rmzKey length (z) exceeds index depth (r�z3indexing past lexsort depth may impact performance.�
)rF)ri)rr�r�r��_get_level_indexerrZr�rryr�r�r$r}rJrLrMrrAr*rBrurEr�rhr
)
rDr�rer�rQZkeylenr|Zlead_keyZ
follow_keyr�rKr%r�rF)rDrGr�O
sD*

 


zMultiIndex.get_loc)�
drop_levelcs�td��fdd��t|ttf�r�t��t|�kr8td��d}xdt|��D]V\}}�j||d�\}}t|t�r�t	j
t��td�}	d|	|<|	}|dkr�|n||@}qHW|�||��fS�j|�}t�t�r�t���t�t�o�|d	k�r�y8��jd	k�r�j
�|d�}
�|
d	g��}|
|fSWnttfk
�r4YnXtd
d��D���s�d���fdd
�	}t���jk�r��j�r�y�jj��dfStk
�r�}zt��|�WYdd}~XnXn|��Sn�d}
x�t��D]�\}
}t|t��s(�j
||
d�}t|t��r$|jd	k�r(|jt��k�r(tdd�}n|}t|t��rR|tdd�k�rJ�q�nt���|
dk�rb|}
n|
|M}
�q�W|
dk�r�tdd�}
�fdd�tt���D�}|
�|
|��fSn �j
�|d�}
|
�|
|g��fSdS)a
        Get location and sliced index for requested label(s)/level(s).

        Parameters
        ----------
        key : label or sequence of labels
        level : int/level name or list thereof, optional
        drop_level : bool, default True
            If ``False``, the resulting index will not drop any level.

        Returns
        -------
        loc : A 2-tuple where the elements are:
              Element 0: int, slice object or boolean array
              Element 1: The resulting sliced multiindex/index. If the key
              contains all levels, this will be ``None``.

        See Also
        --------
        MultiIndex.get_loc  : Get location for a label or a tuple of labels.
        MultiIndex.get_locs : Get location for a label/slice/list/mask or a
                              sequence of such.

        Examples
        --------
        >>> mi = pd.MultiIndex.from_arrays([list('abb'), list('def')],
        ...                                names=['A', 'B'])

        >>> mi.get_loc_level('b')
        (slice(1, 3, None), Index(['e', 'f'], dtype='object', name='B'))

        >>> mi.get_loc_level('e', level='B')
        (array([False,  True, False]), Index(['b'], dtype='object', name='A'))

        >>> mi.get_loc_level(['b', 'e'])
        (1, None)
        )r�csh|s�|S�|}}�fdd�|D�}x8t|dd�D](}y|j|�}Wq8tk
r^|SXq8W|S)Ncsg|]}�j|��qSrF)r�)rsr|)rDrFrGrt�
szIMultiIndex.get_loc_level.<locals>.maybe_mi_droplevels.<locals>.<listcomp>T)r])r`�	droplevelr[)r�rhr�Z
orig_indexrar|)rDrFrG�maybe_mi_droplevels�
s
z5MultiIndex.get_loc_level.<locals>.maybe_mi_droplevelsz:Key for location must have same length as number of levelsN)rm)riTrcss|]}t|t�VqdS)N)r�rJ)rsr%rFrFrGr�sz+MultiIndex.get_loc_level.<locals>.<genexpr>cs<|dkr�j��}�fdd�tt���D�}|�||��fS)Ncs"g|]}�|tdd�kr|�qS)N)rJ)rsr|)r�rFrGrtszGMultiIndex.get_loc_level.<locals>.partial_selection.<locals>.<listcomp>)r�r�rZ)r�r��ilevels)r�r�rD)r�rG�partial_selections
z3MultiIndex.get_loc_level.<locals>.partial_selectioncs"g|]}�|tdd�kr|�qS)N)rJ)rsr|)r�rFrGrtBsz,MultiIndex.get_loc_level.<locals>.<listcomp>)N)r�r�r�rzrZr�rv�
get_loc_levelrJrAr)r�rhr�rYrrpr�ryr�r�rrur�rKr�)rDr�rmr�rkr�r%rQrar�r�r��er|Zk_indexr�rF)r�r�r�rDrGr��
sl'






zMultiIndex.get_loc_levelcCs�|j|}|j|}||fdd�}t|t��rByJ|jdk	rH|j|j�}nd}|jdk	rd|j|j�}nt|�d}|j}	Wn6t	k
r�|j
|j|j|jdd�}}|j}	YnXt|t�s�t|t�r�t|d|�}t|d|�}||||	�S|dk�s|jdk�s|	dk	�r|||d|	�S|j
|d	d
�}
|j
|dd
�}t|
||	�Sn�|j||�}|dk�sd|jdk�r�tj||ktdd
�}
|
j��s�t	|��|
S|j
|d	d
�}
|j
|dd
�}|
|k�r�t	|��t|
|�SdS)Nc
Ss�tj|||�}|dk	rxt|�t|�krxddlm}||�}|jt|��}|t|�j|�j	�d�}|j
|�}	tj|	�}	n,tjt|�t
d�}	d|	tj||t|�jd�<|	S)Nr)r9)riT)�
assume_unique)rAr*rZr r9r�rr.rTrNr�r3r)r�Zin1dry)
r�rKrr�rE�rr9r�rk�mrFrFrG�convert_indexerPs
z6MultiIndex._get_level_indexer.<locals>.convert_indexerrr=rQ)rzr�rKr�)ryrdF)rirW)rhrEr�rJr�r�rKrZrrZ
slice_indexerrr$r�r�rAr�r�rp)rDr�rmr�r�r}r�r�rKrr|rUrnZlocsrFrFrGr�HsH




 

zMultiIndex._get_level_indexercs�ddlm�dd�ttj|��D�}|rL|d|jkrLtd|�d|j����t|��d}�d	���fd
d�}|f�fdd
�	}�x,t|�D�]\}}tj|�r�t	j
|�}|||�|d�}q�t|��rDd}xR|D]J}	y,||j|	||d��}
|dkr�|
n||
B}Wq�t
k
�rw�Yq�Xq�W|dk	�r2|||d�}nt	jgt	jd�Sq�tj|��r^|d|d�}q�t|t��r�|||j|||d��|d�}q�|||j||dd�d�|d�}q�W|dk�r�t	jgt	jd�St|���s�tt|���|j||�}|jS)a
        Get location for a sequence of labels.

        Parameters
        ----------
        seq : label, slice, list, mask or a sequence of such
           You should use one of the above for each level.
           If a level should not be used, set it to ``slice(None)``.

        Returns
        -------
        numpy.ndarray
            NumPy array of integers suitable for passing to iloc.

        See Also
        --------
        MultiIndex.get_loc : Get location for a label or a tuple of labels.
        MultiIndex.slice_locs : Get slice location given start label(s) and
                                end label(s).

        Examples
        --------
        >>> mi = pd.MultiIndex.from_arrays([list('abb'), list('def')])

        >>> mi.get_locs('b')  # doctest: +SKIP
        array([1, 2], dtype=int64)

        >>> mi.get_locs([slice(None), ['e', 'f']])  # doctest: +SKIP
        array([1, 2], dtype=int64)

        >>> mi.get_locs([[True, False, True], slice('e', 'f')])  # doctest: +SKIP
        array([2], dtype=int64)
        r)r2cSsg|]\}}|r|�qSrFrF)rsr|�srFrFrGrt�sz'MultiIndex.get_locs.<locals>.<listcomp>r=zIMultiIndex slicing requires the index to be lexsorted: slicing on levels z, lexsort depth N)r~cs`t|t�r.tj�td�}d||<|j�d}n*tj|�rXt|��krLt	d��|j�d}�|�S)N)riTrzLcannot index with a boolean indexer that is not the same length as the index)
r�rJrAr)r�rNr1r2rZr[)r�r�)r2r�rFrG�_convert_to_indexer�s

z0MultiIndex.get_locs.<locals>._convert_to_indexercs*|dkrttj���}|dkr"|S||@S)N)r.rAr*)Zidxrr�)r�rFrG�_update_indexer�s
z,MultiIndex.get_locs.<locals>._update_indexer)r�)rmr�)riF)rmr�ro)�pandas.core.indexes.numericr2rur1Zis_true_slicesr$rrZr2rAr3r"r�rr�r	Z
is_null_slicer�rJr�r�r��_reorder_indexerr�)rD�seqZtrue_slicesr�r�r�r|r%Zindexersr�ZidxrsrF)r2r�rG�get_locs�sR"






zMultiIndex.get_locs.)r�r�r~c
CsJ|j�rnd}xXt|�D]L\}}t|�r|s|j|j|�}||dk}|dd�|dd�kj�}qW|sn|St|�}t�}x�t|�D]�\}}tj	|�r�t
j|�|}	n�t|��rt
jt|j|�t
j
d�t|j|�}
|j|j|�}||dk}t
jt|��|
|<|
|j||}	nt
j|�|}	|	f|}q�Wt
j|�}||S)aq
        Reorder an indexer of a MultiIndex (self) so that the label are in the
        same order as given in seq

        Parameters
        ----------
        seq : label/slice/list/mask or a sequence of such
        indexer: an Int64Index indexer of self

        Returns
        -------
        indexer : a sorted Int64Index indexer of self ordered as seq
        FrNr=)riro)rrur"rhrSrprZr�r1r2rAr*Zonesr�rEr)
rDr�r�Z	need_sortr|r%Zk_codesr��keysZ	new_orderZ
key_order_mapZ
level_indexer�indrFrFrGr�,s4 


zMultiIndex._reorder_indexercs�|r|r||krtd��|jdj||�\}}|j||�\��t|j�}|d||�|d<��fdd�|jD�}|d||d<t|||jdd�S)av
        Slice index between two labels / tuples, return new MultiIndex

        Parameters
        ----------
        before : label or tuple, can be partial. Default None
            None defaults to start
        after : label or tuple, can be partial. Default None
            None defaults to end

        Returns
        -------
        truncated : MultiIndex
        zafter < beforercsg|]}|����qSrFrF)rsr})r�rdrFrGrt�sz'MultiIndex.truncate.<locals>.<listcomp>F)rhrErTrU)r[rhr}rzrEr:r`)rDZbefore�afterr|rUr�rlrF)r�rdrG�truncateis
zMultiIndex.truncatecCs&|j|�rdSt|t�sdSt|t�sVt|j�s4dSt|�t|�krHdSt|j|j�S|j	|j	krfdSt|�t|�krzdSx�t
|j	�D]�}|j|}||dk}tj
tj|j|j�|dd�}|j|}||dk}tj
tj|j|j�|dd�}t|�dk�rt|�dk�rq�t||�s�dSq�WdS)z�
        Determines if two MultiIndex objects have the same labeling information
        (the levels themselves do not necessarily have to be the same)

        See Also
        --------
        equal_levels
        TFr=)r6rroro)�is_r�r.r:r#rirZr*r�r�r�rErZtake_ndrAr3rh)rDr�r|Z
self_codesZself_valuesZother_codesZother_valuesrFrFrGri�s8	






zMultiIndex.equalscCsB|j|jkrdSx,t|j�D]}|j|j|j|�sdSqWdS)zT
        Return True if the levels of both MultiIndex objects are the same

        FT)r�r�rhri)rDr�r|rFrFrG�equal_levels�szMultiIndex.equal_levelscCsx|j|�|j|�|j|�\}}t|�dks8|j|�r<|St|j�sNtd��tj	|j
|j
g|d�}tjt
|�d|d�S)a/
        Form the union of two MultiIndex objects

        Parameters
        ----------
        other : MultiIndex or array / Index of tuples
        sort : False or None, default None
            Whether to sort the resulting Index.

            * None : Sort the result, except when

              1. `self` and `other` are equal.
              2. `self` has length 0.
              3. Some values in `self` or `other` cannot be compared.
                 A RuntimeWarning is issued in this case.

            * False : do not sort the result.

            .. versionadded:: 0.24.0

            .. versionchanged:: 0.24.1

               Changed the default value from ``True`` to ``None``
               (without change in behaviour).

        Returns
        -------
        Index

        Examples
        --------
        >>> idx1 = pd.MultiIndex.from_arrays(
        ...     [[1, 1, 2, 2], ["Red", "Blue", "Red", "Blue"]]
        ... )
        >>> idx1
        MultiIndex([(1,  'Red'),
            (1, 'Blue'),
            (2,  'Red'),
            (2, 'Blue')],
           )
        >>> idx2 = pd.MultiIndex.from_arrays(
        ...     [[3, 3, 2, 2], ["Red", "Green", "Red", "Green"]]
        ... )
        >>> idx2
        MultiIndex([(3,   'Red'),
            (3, 'Green'),
            (2,   'Red'),
            (2, 'Green')],
           )

        >>> idx1.union(idx2)
        MultiIndex([(1,  'Blue'),
            (1,   'Red'),
            (2,  'Blue'),
            (2, 'Green'),
            (2,   'Red'),
            (3, 'Green'),
            (3,   'Red')],
           )

        >>> idx1.union(idx2, sort=False)
        MultiIndex([(1,   'Red'),
            (1,  'Blue'),
            (2,   'Red'),
            (2,  'Blue'),
            (3,   'Red'),
            (3, 'Green'),
            (2, 'Green')],
           )
        rzjCan only union MultiIndex with MultiIndex or Index of tuples, try mi.to_flat_index().union(other) instead.)r�)rcrT)�_validate_sort_keyword�_assert_can_do_setop�_convert_can_do_setoprZrir#rirrZfast_unique_multipler�r:r�rv)rDr�r��result_names�uniq_tuplesrFrFrG�union�sG


zMultiIndex.unioncs0|j|�|j|�|j|�\}}|j|�r>|jr:|j�S|St|j�sbt|j	gg|j
|dd�S|j}|j}d}|jr�|jr�y|j
||�d}d}Wntk
r�YnXtj|�}|dkr�t|��t����fdd�|D�}|dkr�t|�}t|�dk�rt|j	gg|j
|dd�Stjt|�d|d�SdS)a�
        Form the intersection of two MultiIndex objects.

        Parameters
        ----------
        other : MultiIndex or array / Index of tuples
        sort : False or None, default False
            Sort the resulting MultiIndex if possible

            .. versionadded:: 0.24.0

            .. versionchanged:: 0.24.1

               Changed the default from ``True`` to ``False``, to match
               behaviour from before 0.24.0

        Returns
        -------
        Index
        F)rhrErTrUNrcs,g|]$}|�kr|�kp �j|�r|�qSrF)�add)rsr�)�
other_uniq�seenrFrGrth
sz+MultiIndex.intersection.<locals>.<listcomp>)rcrT)r�r�r�riZhas_duplicatesrr#rir:rhr�r�rZ_inner_indexerrYr�setr`rZr�rv)rDr�r�r�ZlvalsZrvalsr�Zinner_tuplesrF)r�r�rG�intersection/
sJ






zMultiIndex.intersectioncCs�|j|�|j|�|j|�\}}t|�dkr2|S|j|�rVt|jgg|j|dd�S|j�}|j	|�}|j
|d	kj�d�}tj
tj|j�|dd�}|jj
|�}|dkr�t|�}t|�dkr�tgg|jgg|j|dd�Stj|d|d�SdS)
a�
        Compute set difference of two MultiIndex objects

        Parameters
        ----------
        other : MultiIndex
        sort : False or None, default None
            Sort the resulting MultiIndex if possible

            .. versionadded:: 0.24.0

            .. versionchanged:: 0.24.1

               Changed the default value from ``True`` to ``None``
               (without change in behaviour).

        Returns
        -------
        diff : MultiIndex
        rF)rhrErTrUr=T)r�N)rcrTro)r�r�r�rZrir:rhr�Z_get_unique_indexrSr�rNrAZ	setdiff1dr*�sizer�r`r�)rDr�r�r��thisr�Z
label_diff�
differencerFrFrGr�z
s2






zMultiIndex.differencecCs�|j}t|t�s~t|�dkr<tgg|jgg|jdd�}q�d}ytj|�}Wq�tk
rz}zt|�|�WYdd}~Xq�Xn|j|jkr�|jnd}||fS)NrF)rhrErUz.other must be a MultiIndex or a list of tuples)rTr�r.rZr:r�r�rY)rDr�r�r=rrFrFrGr��
s



z MultiIndex._convert_can_do_setopcCsPt|�}t|�rd}t|��n.t|�s<tdt|��d���n|dkrL|j�S|S)Nz3> 1 ndim Categorical are not supported at this timezSetting z5 dtype to anything other than object is not supportedT)r%rrr#rYr�r�)rDrirWr=rFrFrGrR�
s
zMultiIndex.astype)rQc	Cs�t|t�s |fd|jd}nt|�|jkr6td��g}g}xht||j|j�D]T\}}}||krxt|�}|j||�}n
|j	|�}|j
|�|j
tjt|�||��qPWt
|||jdd�S)a
        Make new MultiIndex inserting new item at location

        Parameters
        ----------
        loc : int
        item : tuple
            Must be same length as number of levels in the MultiIndex

        Returns
        -------
        new_index : Index
        r�r=z0Item must have length equal to number of levels.F)rhrErTrU)r�)r�r�r�rZr[rvrhrE�insertr�r�rArr:rT)	rDrQ�itemr�rlr%rmr}Zlev_locrFrFrGr��
s


zMultiIndex.insertcs(�fdd�|jD�}t|j||jdd�S)z}
        Make new index with passed location deleted

        Returns
        -------
        new_index : MultiIndex
        csg|]}tj|���qSrF)rArO)rsr})rQrFrGrtsz%MultiIndex.delete.<locals>.<listcomp>F)rhrErTrU)rEr:rhrT)rDrQrlrF)rQrGrOszMultiIndex.deletecCs$|j|jkr|jnd}tj||d�S)N)rT)rTr:r�)rDZjoinedr�rTrFrFrG�_wrap_joined_indexszMultiIndex._wrap_joined_indexcCsh|dkr(tj||jd�j}tj|j|�S|j|�}|j|�}|jdkrZt	j
t|�t	jd�S|j|�SdS)N)rTr)ri)
r:r�rTr�rrTr�rr�rAr)rZZbool_)rDr�rm�numZlevsrFrFrGrTs


zMultiIndex.isin)	NNNNNFNTT)NN)NN)NN)NFTF)NFT)NFTF)NFT)NN)NNNNFNF)N)N)F)F)N)r�)NNNFr�NT)NT)r)NN)rp)F)N)TN)rTN)TNN)N)N)NrD)rD���ro)r�ro)rTT)NNNN)NNN)NNNN)r�)N)rT)rN)NN)N)F)N)T)N)�rIrJrKrLr.Z
_deprecations�	frozensetZ_typr1r`r�reZ_comparablesZ	set_names�renamer�r	rbrcr�r\rrrrd�classmethodrr�r�r�r�r��propertyr�r�r�r�r�rrhr^r�r�r�rEr_r�r�r�rr�r�rWrAr�r�r�r�rrir�r�r�r�r�r�r�r�rr_r�r�rarTrrr�rrrr�rrrr�rrrr!r"r#rr$r{r(r,r0r5rr/�_index_doc_kwargsr�r9r�r&rArqrRrHrWrYr\rbrlrmrnrqrrrurSrxrrr
r|r}r{r�r�r�r�r�rrrrr2r�r�rir�r�r�r�r�rRr�rOr�rT�
__classcell__rFrF)rrGr:�sZ
O'?A9:C	
$
k


S
,"E:%$5"CW!"5:NC(18p
b9"8\K8(r�)r�cCs�tt|��}t|�}|d|d�}||}x�||dd�D]�}g}xrtt||��D]`\}	\}
}|	|dkr�|j|�|j|�P|
|kr�|j|�qV|j||	d��|j|�PqVW|}q>Wtt|��S)Nr=)rzrvrZrur�r�)Z
label_listr�r�Zpivotedr%rk�prev�curZ
sparse_curr|�p�trFrFrGr�'s$


r�)r~cCstjdtjdij|d�S)NZNaT�NaN)rAZ
datetime64Ztimedelta64�get)rirFrFrGr�Csr�cCsj|}t|t�rBxV|D](}y|jd�}Wqtk
r:|SXqWn$y|jd�}Wntk
rdYnX|S)z�
    Attempt to drop level or levels from the given index.

    Parameters
    ----------
    index: Index
    key : scalar or tuple

    Returns
    -------
    Index
    r)r�r�r�r[)rr�Zoriginal_indexr�rFrFrGrpGs

rpF)rWr~cCs"t||�}|r|j�}d|j_|S)a
    Coerce the array_like indexer to the smallest integer dtype that can encode all
    of the given categories.

    Parameters
    ----------
    array_like : array-like
    categories : array-like
    copy : bool

    Returns
    -------
    np.ndarray
        Non-writeable.
    F)rrWr�r�)Z
array_like�
categoriesrWrFrFrGr�fs

r�)rr�)F)s�sysrZtypingrrrrrrr	r
rrrLZnumpyrAZpandas._configr
Zpandas._libsrrrrMrZpandas._libs.hashtablerZpandas._typingrrZpandas.compat.numpyrr8Z
pandas.errorsrrrZpandas.util._decoratorsrrrZpandas.core.dtypes.castrZpandas.core.dtypes.commonrrrrr r!r"r#r$r%Zpandas.core.dtypes.dtypesr&Zpandas.core.dtypes.genericr'r(r)Zpandas.core.dtypes.missingr*r+Zpandas.core.algorithms�coreZ
algorithmsZpandas.core.arraysr,Zpandas.core.arrays.categoricalr-Zpandas.core.common�commonr1Zpandas.core.indexes.base�indexes�baser.r.r/r0Zpandas.core.indexes.frozenr1r�r2Zpandas.core.missingrwZpandas.core.sortingr3r4r5Zpandas.io.formats.printingr6r7r8r r9r-r��updateZBaseMultiIndexCodesEnginerNr<rSrPr:Z_add_numeric_methods_disabledZ%_add_numeric_methods_add_sub_disabledZ_add_logical_methods_disabledrbr�r_r�rpr�r�r�rFrFrFrG�<module>s�00
')#