HOME


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

���hPc�@s�ddlmZddlmZddlZddlmZddlmZm	Z	m
Z
mZmZm
Z
ddlmZddlZddlmZddlmZmZmZdd	lmZmZmZmZdd
lm Z!ddl"m#Z#m$Z$m%Z%ddl&m'Z'm(Z(dd
l)m*Z*m+Z+m,Z,ddl-m.Z.m/Z/m0Z0m1Z1m2Z2m3Z3m4Z4m5Z5m6Z6m7Z7m8Z8m9Z9m:Z:ddl;m<Z<ddl=m>Z>m?Z?ddl@mAZAddlBmCZCmDZDmEZEddlFmGZGddlHmIZImJZJddlKjLjMZMddlKmNZNmOZOmPZPmQZQddlRmSZSddlTmUZUmVZVddlWmXZXmYZYmZZZm[Z[ddl\jLj]Z^ddl_m`Z`maZambZbddlcmdZdmeZeddlfmgZgddlhmiZiddljmkZkddllmmZmdd �Znd!d"�ZoGd#d$�d$eVeZ�ZpeJepd%d&gd'd(�eJepd)d*d+d,d-d.d/d0gd1d(�Gd2d3�d3eIeZeY���Zqd4d5�Zrejsd6�d7d8�Ztd9d:�Zud;d<�ZvdS)=�)�QUOTE_NONNUMERIC)�partialN)�get_terminal_size)�Dict�Hashable�List�Type�Union�cast)�warn)�
get_option)�NaT�algos�	hashtable)�	ArrayLike�Dtype�Ordered�Scalar)�function)�cache_readonly�deprecate_kwarg�doc)�validate_bool_kwarg�validate_fillna_kwargs)�coerce_indexer_dtype�maybe_cast_to_extension_array�maybe_infer_to_datetimelike)
�ensure_int64�
ensure_object�is_categorical_dtype�is_datetime64_dtype�is_dict_like�is_dtype_equal�is_extension_array_dtype�is_integer_dtype�is_list_like�is_object_dtype�	is_scalar�is_timedelta64_dtype�needs_i8_conversion)�CategoricalDtype)�
ABCIndexClass�	ABCSeries)�is_hashable)�is_valid_nat_for_dtype�isna�notna)�ops)�PandasDelegate�delegate_names)�_get_data_algo�	factorize�take_1d�unique1d)�shift)�_T�NDArrayBackedExtensionArray)�ExtensionArray�NoNewAttributesMixin�PandasObject�_shared_docs)�array�
extract_array�sanitize_array)�check_array_indexer�deprecate_ndim_indexing)�interpolate_2d)�unpack_zerodim_and_defer)�nargsort)�consolecs.d�j�d��t����fdd��}�|_|S)N�__csDt|�r t|�t|�kr td��|js6�dkr6td��t|t��rDd}t|j�t|j�krht|d��n>|jr�|j|jkj�r�t|��nt	|j�t	|j�ks�t|��|j|jks�td	��|jr�|jj
|j�r�t||j�}n|j}t
|j��}||�}|jdk|dkB}|j��r@�dk�r8d||jdk|dk@<nd
||<|St|��r�||jk�r�|jj|�}t
|j��|�}�dk�r�|jdk}d
||<|S�dk�r�tjt|�td�S�dk�r�tjt|�td�Std��d���n`�dk�rtd��dt|��d���t|t��r&t|j��r&�||�St
tj|���tj|��SdS)NzLengths must match.�__lt__�__gt__�__le__�__ge__z7Unordered Categoricals can only compare equality or notz?Categoricals can only be compared if 'categories' are the same.z! Categories are different lengthsz:Categoricals can only be compared if 'ordered' is the same��__ne__TF�__eq__)�dtypez$Cannot compare a Categorical for op z( with a scalar, which is not a category.z with type zB.
If you want to compare values, use 'np.asarray(cat) <op> other'.)rIrJrKrL���rQrQrQ>rOrJrLrQ)rOrN)r%�len�
ValueError�ordered�	TypeError�
isinstance�Categorical�
categories�all�set�equals�_get_codes_for_values�_codes�getattr�anyr'�get_loc�np�zeros�bool�ones�typer;r)rPr?)�self�other�msg�other_codes�f�ret�mask�i)�op�opname��@/tmp/pip-build-5_djhm0z/pandas/pandas/core/arrays/categorical.py�funcDs`









z_cat_compare_op.<locals>.func)�__name__rE)rnrrrp)rnrorq�_cat_compare_opAsPrtcs\t|�y|jj|�}Wnttfk
r0dSXt|�rB|�kSt�fdd�|D��SdS)aO
    Helper for membership check for ``key`` in ``cat``.

    This is a helper method for :method:`__contains__`
    and :class:`CategoricalIndex.__contains__`.

    Returns True if ``key`` is in ``cat.categories`` and the
    location of ``key`` in ``categories`` is in ``container``.

    Parameters
    ----------
    cat : :class:`Categorical`or :class:`categoricalIndex`
    key : a hashable object
        The key to check membership for.
    container : Container (e.g. list-like or mapping)
        The container to check for membership in.

    Returns
    -------
    is_in : bool
        True if ``key`` is in ``self.categories`` and location of
        ``key`` in ``categories`` is in ``container``, else False.

    Notes
    -----
    This method does not check for NaN values. Do that separately
    before calling this method.
    Fc3s|]}|�kVqdS)Nrp)�.0Zloc_)�	containerrprq�	<genexpr>�szcontains.<locals>.<genexpr>N)�hashrXr`�KeyErrorrUr'r_)�cat�keyrv�locrp)rvrq�contains�sr}csJeZdZdZdZedd�Zeje	dg�BZdZ
d�dd	�Zed
d��Z
e
jdd��Z
eed
�dd��Zeed
�dd��Zeedd
�dd��Zed�dd��Zd�dd�Zd�eeed�dd�Zeed
�dd��Zeed
�dd�Z e Z!ed�d d!��Z"ed�d"d#��Z#ee$j%d
�d$d%��Z&d�d&d'�Z'edd(�d)d*�Z(d�d+d,�Z)d�d-d.�Z*d�d/d0�Z+d�d1d2�Z,d�d3d4�Z-d�d5d6�Z.d�d7d8�Z/d�d9d:�Z0d�d;d<�Z1d=d>�Z2e3e4j5�Z6e3e4j7�Z8e3e4j9�Z:e3e4j;�Z<e3e4j=�Z>e3e4j?�Z@d�d?d@�ZAdAdB�ZBd�e$j%d
�dCdD�ZCdEdF�ZDdGdH�ZEedIdJ��ZFd�dKdL�ZGeHeIdMddN�d�dPdQ��ZJdRdS�ZKeKZLdTdU�ZMeMZNdVdW�ZOd�dXdY�ZPdZd[�ZQd\d]�ZRd^d_�ZSdʇfdadb�	ZTd�eeeUdd�dedf�ZVdgdh�ZWd�didj�ZXdkdl�ZYd�dmdn�ZZd�e[ee[do�dpdq�Z\ee$j%d
�drds��Z]e$j%ddt�dudv�Z^d�edw�dxdy�Z_dzd{�Z`ed
�d|d}�Zad�eUd
�dd��Zbd�d��ZceUd
�d�d��ZdeUd
�d�d��Zed�eUd
�d�d��ZfeUd
�d�d��Zgd�d��Zhd�d��Zid�d��Zjekele$j%fd
�d�d��Zmd�eUed��d�d��Zneod�d�d��d�d�d���Zpeod�d�d��d�d�d���Zqd�d�d��Zrd�d��Zsd�d��Zted�d���Zud�d��Zvd�d��Zwd�d��Zxed�d���Zyed�d���Zzd�d��Z{d�ed��d�d��Z|�Z}S)�rWa
    Represent a categorical variable in classic R / S-plus fashion.

    `Categoricals` can only take on only a limited, and usually fixed, number
    of possible values (`categories`). In contrast to statistical categorical
    variables, a `Categorical` might have an order, but numerical operations
    (additions, divisions, ...) are not possible.

    All values of the `Categorical` are either in `categories` or `np.nan`.
    Assigning values outside of `categories` will raise a `ValueError`. Order
    is defined by the order of the `categories`, not lexical order of the
    values.

    Parameters
    ----------
    values : list-like
        The values of the categorical. If categories are given, values not in
        categories will be replaced with NaN.
    categories : Index-like (unique), optional
        The unique categories for this categorical. If not given, the
        categories are assumed to be the unique values of `values` (sorted, if
        possible, otherwise in the order in which they appear).
    ordered : bool, default False
        Whether or not this categorical is treated as a ordered categorical.
        If True, the resulting categorical will be ordered.
        An ordered categorical respects, when sorted, the order of its
        `categories` attribute (which in turn is the `categories` argument, if
        provided).
    dtype : CategoricalDtype
        An instance of ``CategoricalDtype`` to use for this categorical.

    Attributes
    ----------
    categories : Index
        The categories of this categorical
    codes : ndarray
        The codes (integer positions, which point to the categories) of this
        categorical, read only.
    ordered : bool
        Whether or not this Categorical is ordered.
    dtype : CategoricalDtype
        The instance of ``CategoricalDtype`` storing the ``categories``
        and ``ordered``.

    Methods
    -------
    from_codes
    __array__

    Raises
    ------
    ValueError
        If the categories do not validate.
    TypeError
        If an explicit ``ordered=True`` is given but no `categories` and the
        `values` are not sortable.

    See Also
    --------
    CategoricalDtype : Type for categorical data.
    CategoricalIndex : An Index with an underlying ``Categorical``.

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

    Examples
    --------
    >>> pd.Categorical([1, 2, 3, 1, 2, 3])
    [1, 2, 3, 1, 2, 3]
    Categories (3, int64): [1, 2, 3]

    >>> pd.Categorical(['a', 'b', 'c', 'a', 'b', 'c'])
    ['a', 'b', 'c', 'a', 'b', 'c']
    Categories (3, object): ['a', 'b', 'c']

    Ordered `Categoricals` can be sorted according to the custom order
    of the categories and can have a min and max value.

    >>> c = pd.Categorical(['a', 'b', 'c', 'a', 'b', 'c'], ordered=True,
    ...                    categories=['c', 'b', 'a'])
    >>> c
    ['a', 'b', 'c', 'a', 'b', 'c']
    Categories (3, object): ['c' < 'b' < 'a']
    >>> c.min()
    'c'
    i�F)rT�tolistZcategoricalNcstj�|||�}|r4t�|j�|_|jj|�|_dStjd�}t	��r`|jdkr�t�j|j
�}n�t�tt
f�s�t�dd��t�tj�s�tj���t��dkr�tjd�nd}t��}|j�r؇fdd�tj|�dD��t�d|d��|jdk�r�yt�dd	�\}}Wnrtk
�rL}	z(t�dd	�\}}|j
�r<td
�|	�WYdd}	~	Xn.tk
�rx}	ztd�|	�WYdd}	~	XnXt||j
�}nFt	�j��r�t�t
��r��jjn�j}
t|
�jj|j�}nt�|j�}|j��r�tj |j!|jd�}|||<|}|jj|�|_t||j�|_dS)NFT)Z
convert_datesr�Ocsg|]}�|�qSrprp)ru�idx)�valuesrprq�
<listcomp>Rsz(Categorical.__init__.<locals>.<listcomp>)rP)�sortzl'values' is not ordered, please explicitly specify the categories order by passing in a categories argument.z3> 1 ndim Categorical are not supported at this time)"r*�_from_values_or_dtyperrXr]�_dtype�update_dtyperar?rrTrVr+r,r�ndarray�comZconvert_to_list_likerRrPr/r_�whererAr5rUrS�NotImplementedErrorZ_values�codes�recode_for_categoriesr\rd�shape)rfr�rXrTrP�fastpath�	null_maskZsanitize_dtyper��errZ	old_codesZ
full_codesrp)r�rq�__init__/sX




zCategorical.__init__cCs|jjS)a�
        The categories of this categorical.

        Setting assigns new values to each category (effectively a rename of
        each individual category).

        The assigned value has to be a list-like object. All items must be
        unique and the number of items in the new categories must be the same
        as the number of items in the old categories.

        Assigning to `categories` is a inplace operation!

        Raises
        ------
        ValueError
            If the new categories do not validate as categories or if the
            number of new categories is unequal the number of old categories

        See Also
        --------
        rename_categories : Rename categories.
        reorder_categories : Reorder categories.
        add_categories : Add new categories.
        remove_categories : Remove the specified categories.
        remove_unused_categories : Remove categories which are not used.
        set_categories : Set the categories to the specified ones.
        )rPrX)rfrprprqrX�szCategorical.categoriescCsBt||jd�}|jjdk	r8t|jj�t|j�kr8td��||_dS)N)rTzKnew categories need to have the same number of items as the old categories!)r*rTrPrXrRrSr�)rfrX�	new_dtyperprprqrX�s
)�returncCs|jjS)zF
        Whether the categories have an ordered relationship.
        )rPrT)rfrprprqrT�szCategorical.orderedcCs|jS)zT
        The :class:`~pandas.api.types.CategoricalDtype` for this instance.
        )r�)rfrprprqrP�szCategorical.dtypecCstS)N)rW)rfrprprq�_constructor�szCategorical._constructorcCst||d�S)N)rP)rW)�clsZscalarsrP�copyrprprq�_from_sequence�szCategorical._from_sequencecCsdS)Nrp)rfZboxedrprprq�
_formatter�szCategorical._formatterT)rPr�r�cCs�t|�rNttttf|�}|jj|�}|r2|j�n|}||jkrD|S|j|�St	|�rdt
|||d�St|�r�|j�j
�r�td��tj
|||d�S)aZ
        Coerce this type to another dtype

        Parameters
        ----------
        dtype : numpy dtype or pandas type
        copy : bool, default True
            By default, astype always returns a newly allocated object.
            If copy is set to False and dtype is categorical, the original
            object is returned.
        )rPr�z#Cannot convert float NaN to integer)rr
r	�strr*rPr�r��
_set_dtyper#r?r$r/r_rSra)rfrPr�rprprq�astype�s

zCategorical.astypecCs|jjS)z6
        return the size of a single category
        )rX�itemsize)rfrprprqr��szCategorical.itemsizecCst|�S)z�
        Return a list of the values.

        These are each a scalar type, which is a Python scalar
        (for str, int, float) or a pandas scalar
        (for Timestamp/Timedelta/Interval/Period)
        )�list)rfrprprqr~�szCategorical.tolistcCsddlm}m}m}m}||�}	t|t�o2|jdk	}
|
r�|jj�rP||dd�}	nVt	|j�rh||dd�}	n>t
|j�r�||dd�}	n&|jj�r�|dkr�dddg}|	j|�}	|
r�|j}t
||	|�}n@|	js�|	j�}
|	j�}t
||
|�}t|d	d
�}nt|	d	d
�}|}|||dd�S)
aA
        Construct a Categorical from inferred values.

        For inferred categories (`dtype` is None) the categories are sorted.
        For explicit `dtype`, the `inferred_categories` are cast to the
        appropriate type.

        Parameters
        ----------
        inferred_categories : Index
        inferred_codes : Index
        dtype : CategoricalDtype or 'category'
        true_values : list, optional
            If none are provided, the default ones are
            "True", "TRUE", and "true."

        Returns
        -------
        Categorical
        r)�Index�to_datetime�
to_numeric�to_timedeltaNZcoerce)�errors�True�TRUE�trueF)rTT)rPr�)�pandasr�r�r�r�rVr*rX�
is_numericr r(Z
is_boolean�isinr�Zis_monotonic_increasingr��sort_values)r�Zinferred_categoriesZinferred_codesrPZtrue_valuesr�r�r�r��catsZknown_categoriesrXr�Zunsortedrprprq�_from_inferred_categories�s2





z%Categorical._from_inferred_categoriescCs�tj|||d�}|jdkr&d}t|��t|�rZt|�rZt|�j�rJtd��|jt	j
d�}n
t	j|�}t|�r~t|�r~td��t|�r�|j
�t|j�ks�|j�dkr�td��|||d	d
�S)al
        Make a Categorical type from codes and categories or dtype.

        This constructor is useful if you already have codes and
        categories/dtype and so do not need the (computation intensive)
        factorization step, which is usually done on the constructor.

        If your data does not follow this convention, please use the normal
        constructor.

        Parameters
        ----------
        codes : array-like of int
            An integer array, where each integer points to a category in
            categories or dtype.categories, or else is -1 for NaN.
        categories : index-like, optional
            The categories for the categorical. Items need to be unique.
            If the categories are not given here, then they must be provided
            in `dtype`.
        ordered : bool, optional
            Whether or not this categorical is treated as an ordered
            categorical. If not given here or in `dtype`, the resulting
            categorical will be unordered.
        dtype : CategoricalDtype or "category", optional
            If :class:`CategoricalDtype`, cannot be used together with
            `categories` or `ordered`.

            .. versionadded:: 0.24.0

               When `dtype` is provided, neither `categories` nor `ordered`
               should be provided.

        Returns
        -------
        Categorical

        Examples
        --------
        >>> dtype = pd.CategoricalDtype(['a', 'b'], ordered=True)
        >>> pd.Categorical.from_codes(codes=[0, 1, 0, 1], dtype=dtype)
        ['a', 'b', 'a', 'b']
        Categories (2, object): ['a' < 'b']
        )rXrTrPNzKThe categories must be provided in 'categories' or 'dtype'. Both were None.zcodes cannot contain NA values)rPz$codes need to be array-like integersrMz1codes need to be between -1 and len(categories)-1T)rPr�rQ)r*r�rXrSr#r$r/r_Zto_numpyra�int64�asarrayrR�max�min)r�r�rXrTrPrhrprprq�
from_codes1s-

&zCategorical.from_codescCs|jj�}d|j_|S)a�
        The category codes of this categorical.

        Codes are an array of integers which are the positions of the actual
        values in the categories array.

        There is no setter, use the other categorical methods and the normal item
        setter to change values in the categorical.

        Returns
        -------
        ndarray[int]
            A non-writable view of the `codes` array.
        F)r]�view�flagsZ	writeable)rf�vrprprqr�ws
zCategorical.codescCs\|rtj||j�}nt||jd�}|rR|jjdk	rRt|j�t|jj�krRtd��||_dS)a�
        Sets new categories inplace

        Parameters
        ----------
        fastpath : bool, default False
           Don't perform validation of the categories for uniqueness or nulls

        Examples
        --------
        >>> c = pd.Categorical(['a', 'b'])
        >>> c
        ['a', 'b']
        Categories (2, object): ['a', 'b']

        >>> c._set_categories(pd.Index(['a', 'c']))
        >>> c
        ['a', 'c']
        Categories (2, object): ['a', 'c']
        )rTNzMnew categories need to have the same number of items than the old categories!)r*�_from_fastpathrTrPrXrRrSr�)rfrXr�r�rprprq�_set_categories�szCategorical._set_categories)rPr�cCs$t|j|j|j�}t|�||dd�S)a+
        Internal method for directly updating the CategoricalDtype

        Parameters
        ----------
        dtype : CategoricalDtype

        Notes
        -----
        We don't do any validation here. It's assumed that the dtype is
        a (valid) instance of `CategoricalDtype`.
        T)rPr�)r�r�rXre)rfrPr�rprprqr��s
zCategorical._set_dtypecCs:t|d�}t|j|d�}|r |n|j�}||_|s6|SdS)a|
        Set the ordered attribute to the boolean value.

        Parameters
        ----------
        value : bool
           Set whether this categorical is ordered (True) or not (False).
        inplace : bool, default False
           Whether or not to set the ordered attribute in-place or return
           a copy of this categorical with ordered set to the value.
        �inplace)rTN)rr*rXr�r�)rf�valuer�r�rzrprprq�set_ordered�s
zCategorical.set_orderedcCst|d�}|jd|d�S)aa
        Set the Categorical to be ordered.

        Parameters
        ----------
        inplace : bool, default False
           Whether or not to set the ordered attribute in-place or return
           a copy of this categorical with ordered set to True.

        Returns
        -------
        Categorical
            Ordered Categorical.
        r�T)r�)rr�)rfr�rprprq�
as_ordered�s
zCategorical.as_orderedcCst|d�}|jd|d�S)af
        Set the Categorical to be unordered.

        Parameters
        ----------
        inplace : bool, default False
           Whether or not to set the ordered attribute in-place or return
           a copy of this categorical with ordered set to False.

        Returns
        -------
        Categorical
            Unordered Categorical.
        r�F)r�)rr�)rfr�rprprq�as_unordered�s
zCategorical.as_unorderedcCs�t|d�}|dkr|jj}t||d�}|r.|n|j�}|rt|jjdk	r�t|j�t|jj�kr�d|j|jt|j�k<nt|j	|j|j�}||_||_
|s�|SdS)ap
        Set the categories to the specified new_categories.

        `new_categories` can include new categories (which will result in
        unused categories) or remove old categories (which results in values
        set to NaN). If `rename==True`, the categories will simple be renamed
        (less or more items than in old categories will result in values set to
        NaN or in unused categories respectively).

        This method can be used to perform more than one action of adding,
        removing, and reordering simultaneously and is therefore faster than
        performing the individual steps via the more specialised methods.

        On the other hand this methods does not do checks (e.g., whether the
        old categories are included in the new categories on a reorder), which
        can result in surprising changes, for example when using special string
        dtypes, which does not considers a S1 string equal to a single char
        python string.

        Parameters
        ----------
        new_categories : Index-like
           The categories in new order.
        ordered : bool, default False
           Whether or not the categorical is treated as a ordered categorical.
           If not given, do not change the ordered information.
        rename : bool, default False
           Whether or not the new_categories should be considered as a rename
           of the old categories or as reordered categories.
        inplace : bool, default False
           Whether or not to reorder the categories in-place or return a copy
           of this categorical with reordered categories.

        Returns
        -------
        Categorical with reordered categories or None if inplace.

        Raises
        ------
        ValueError
            If new_categories does not validate as categories

        See Also
        --------
        rename_categories : Rename categories.
        reorder_categories : Reorder categories.
        add_categories : Add new categories.
        remove_categories : Remove the specified categories.
        remove_unused_categories : Remove categories which are not used.
        r�N)rTrMrQ)rrPrTr*r�rXrRr]r�r�r�)rf�new_categoriesrT�renamer�r�rzr�rprprq�set_categories�s3
zCategorical.set_categoriescslt|d�}|r|n|j�}t��r:�fdd�|jD�|_n&t��rZ�fdd�|jD�|_n�|_|sh|SdS)a�
        Rename categories.

        Parameters
        ----------
        new_categories : list-like, dict-like or callable

            New categories which will replace old categories.

            * list-like: all items must be unique and the number of items in
              the new categories must match the existing number of categories.

            * dict-like: specifies a mapping from
              old categories to new. Categories not contained in the mapping
              are passed through and extra categories in the mapping are
              ignored.

            * callable : a callable that is called on all items in the old
              categories and whose return values comprise the new categories.

            .. versionadded:: 0.23.0.

        inplace : bool, default False
            Whether or not to rename the categories inplace or return a copy of
            this categorical with renamed categories.

        Returns
        -------
        cat : Categorical or None
           With ``inplace=False``, the new categorical is returned.
           With ``inplace=True``, there is no return value.

        Raises
        ------
        ValueError
            If new categories are list-like and do not have the same number of
            items than the current categories or do not validate as categories

        See Also
        --------
        reorder_categories : Reorder categories.
        add_categories : Add new categories.
        remove_categories : Remove the specified categories.
        remove_unused_categories : Remove categories which are not used.
        set_categories : Set the categories to the specified ones.

        Examples
        --------
        >>> c = pd.Categorical(['a', 'a', 'b'])
        >>> c.rename_categories([0, 1])
        [0, 0, 1]
        Categories (2, int64): [0, 1]

        For dict-like ``new_categories``, extra keys are ignored and
        categories not in the dictionary are passed through

        >>> c.rename_categories({'a': 'A', 'c': 'C'})
        ['A', 'A', 'b']
        Categories (2, object): ['A', 'b']

        You may also provide a callable to create the new categories

        >>> c.rename_categories(lambda x: x.upper())
        ['A', 'A', 'B']
        Categories (2, object): ['A', 'B']
        r�csg|]}�j||��qSrp)�get)ru�item)r�rprqr��sz1Categorical.rename_categories.<locals>.<listcomp>csg|]}�|��qSrprp)rur�)r�rprqr��sN)rr�r!rX�callable)rfr�r�rzrp)r�rq�rename_categories@sC
zCategorical.rename_categoriescCs6t|d�}t|jj�t|�kr&td��|j|||d�S)a�
        Reorder categories as specified in new_categories.

        `new_categories` need to include all old categories and no new category
        items.

        Parameters
        ----------
        new_categories : Index-like
           The categories in new order.
        ordered : bool, optional
           Whether or not the categorical is treated as a ordered categorical.
           If not given, do not change the ordered information.
        inplace : bool, default False
           Whether or not to reorder the categories inplace or return a copy of
           this categorical with reordered categories.

        Returns
        -------
        cat : Categorical with reordered categories or None if inplace.

        Raises
        ------
        ValueError
            If the new categories do not contain all old category items or any
            new ones

        See Also
        --------
        rename_categories : Rename categories.
        add_categories : Add new categories.
        remove_categories : Remove the specified categories.
        remove_unused_categories : Remove categories which are not used.
        set_categories : Set the categories to the specified ones.
        r�z=items in new_categories are not the same as in old categories)rTr�)rrZrPrXrSr�)rfr�rTr�rprprq�reorder_categories�s
$
zCategorical.reorder_categoriescCs�t|d�}t|�s|g}t|�t|jj�@}t|�dkrFtd|����t|jj�t|�}t||j	�}|rn|n|j
�}||_t|j
|j�|_
|s�|SdS)a3
        Add new categories.

        `new_categories` will be included at the last/highest place in the
        categories and will be unused directly after this call.

        Parameters
        ----------
        new_categories : category or list-like of category
           The new categories to be included.
        inplace : bool, default False
           Whether or not to add the categories inplace or return a copy of
           this categorical with added categories.

        Returns
        -------
        cat : Categorical with new categories added or None if inplace.

        Raises
        ------
        ValueError
            If the new categories include old categories or do not validate as
            categories

        See Also
        --------
        rename_categories : Rename categories.
        reorder_categories : Reorder categories.
        remove_categories : Remove the specified categories.
        remove_unused_categories : Remove categories which are not used.
        set_categories : Set the categories to the specified ones.
        r�rz0new categories must not include old categories: N)rr%rZrPrXrRrSr�r*rTr�r�rr])rfr�r�Zalready_includedr�rzrprprq�add_categories�s!
zCategorical.add_categoriescs�t|d�}t|�s|g}t|���t|jj�}�fdd�|jjD�}tt|��rndd�|D�}dd�|D�}t|�dkr�td|����|j	||j
d	|d
�S)a
        Remove the specified categories.

        `removals` must be included in the old categories. Values which were in
        the removed categories will be set to NaN

        Parameters
        ----------
        removals : category or list of categories
           The categories which should be removed.
        inplace : bool, default False
           Whether or not to remove the categories inplace or return a copy of
           this categorical with removed categories.

        Returns
        -------
        cat : Categorical with removed categories or None if inplace.

        Raises
        ------
        ValueError
            If the removals are not contained in the categories

        See Also
        --------
        rename_categories : Rename categories.
        reorder_categories : Reorder categories.
        add_categories : Add new categories.
        remove_unused_categories : Remove categories which are not used.
        set_categories : Set the categories to the specified ones.
        r�csg|]}|�kr|�qSrprp)ru�c)�removal_setrprqr�sz1Categorical.remove_categories.<locals>.<listcomp>cSsh|]}t|�r|�qSrp)r0)ru�xrprprq�	<setcomp>sz0Categorical.remove_categories.<locals>.<setcomp>cSsg|]}t|�r|�qSrp)r0)rur�rprprqr�srz(removals must all be in old categories: F)rTr�r�)rr%rZrPrXr_r/rRrSr�rT)rfZremovalsr�Znot_includedr�rp)r�rq�remove_categories�s 
zCategorical.remove_categoriescCs�t|d�}|r|n|j�}tj|jdd�\}}|jdkrZ|ddkrZ|dd�|d}}|jjj|�}t	j
||jd�}||_t
||j�|_|s�|SdS)	a�
        Remove categories which are not used.

        Parameters
        ----------
        inplace : bool, default False
           Whether or not to drop unused categories inplace or return a copy of
           this categorical with unused categories dropped.

        Returns
        -------
        cat : Categorical with unused categories dropped or None if inplace.

        See Also
        --------
        rename_categories : Rename categories.
        reorder_categories : Reorder categories.
        add_categories : Add new categories.
        remove_categories : Remove the specified categories.
        set_categories : Set the categories to the specified ones.
        r�T)Zreturn_inverserrMN)rTrQ)rr�ra�uniquer]�sizerPrX�taker*r�rTr�r)rfr�rzr��invr�r�rprprq�remove_unused_categories s
z$Categorical.remove_unused_categoriescCsj|jj|�}y|j|jj�||jd�Stk
rdtj|jdk�rV|j	t
|�tj�}tj||j�SXdS)a�	
        Map categories using input correspondence (dict, Series, or function).

        Maps the categories to new categories. If the mapping correspondence is
        one-to-one the result is a :class:`~pandas.Categorical` which has the
        same order property as the original, otherwise a :class:`~pandas.Index`
        is returned. NaN values are unaffected.

        If a `dict` or :class:`~pandas.Series` is used any unmapped category is
        mapped to `NaN`. Note that if this happens an :class:`~pandas.Index`
        will be returned.

        Parameters
        ----------
        mapper : function, dict, or Series
            Mapping correspondence.

        Returns
        -------
        pandas.Categorical or pandas.Index
            Mapped categorical.

        See Also
        --------
        CategoricalIndex.map : Apply a mapping correspondence on a
            :class:`~pandas.CategoricalIndex`.
        Index.map : Apply a mapping correspondence on an
            :class:`~pandas.Index`.
        Series.map : Apply a mapping correspondence on a
            :class:`~pandas.Series`.
        Series.apply : Apply more complex functions on a
            :class:`~pandas.Series`.

        Examples
        --------
        >>> cat = pd.Categorical(['a', 'b', 'c'])
        >>> cat
        ['a', 'b', 'c']
        Categories (3, object): ['a', 'b', 'c']
        >>> cat.map(lambda x: x.upper())
        ['A', 'B', 'C']
        Categories (3, object): ['A', 'B', 'C']
        >>> cat.map({'a': 'first', 'b': 'second', 'c': 'third'})
        ['first', 'second', 'third']
        Categories (3, object): ['first', 'second', 'third']

        If the mapping is one-to-one the ordering of the categories is
        preserved:

        >>> cat = pd.Categorical(['a', 'b', 'c'], ordered=True)
        >>> cat
        ['a', 'b', 'c']
        Categories (3, object): ['a' < 'b' < 'c']
        >>> cat.map({'a': 3, 'b': 2, 'c': 1})
        [3, 2, 1]
        Categories (3, int64): [3 < 2 < 1]

        If the mapping is not one-to-one an :class:`~pandas.Index` is returned:

        >>> cat.map({'a': 'first', 'b': 'second', 'c': 'first'})
        Index(['first', 'second', 'first'], dtype='object')

        If a `dict` is used, all unmapped categories are mapped to `NaN` and
        the result is an :class:`~pandas.Index`:

        >>> cat.map({'a': 'first', 'b': 'second'})
        Index(['first', 'second', nan], dtype='object')
        )rXrTrMNrQ)
rX�mapr�r]r�rTrSrar_�insertrR�nanr�)rfZmapperr�rprprqr�GsEzCategorical.mapcCsD|j}|jdkrtd��|j|�}t||d|d�}|j||jdd�S)a�
        Shift Categorical by desired number of periods.

        Parameters
        ----------
        periods : int
            Number of periods to move, can be positive or negative
        fill_value : object, optional
            The scalar value to use for newly introduced missing values.

            .. versionadded:: 0.24.0

        Returns
        -------
        shifted : Categorical
        rMzCategorical with ndim > 1.r)�axis�
fill_valueT)rPr�)r��ndimr��_validate_fill_valuer8r�rP)rfZperiodsr�r�rprprqr8�s

zCategorical.shiftcCs:t|�rd}n(||jkr&|jj|�}ntd|�d���|S)aM
        Convert a user-facing fill_value to a representation to use with our
        underlying ndarray, raising ValueError if this is not possible.

        Parameters
        ----------
        fill_value : object

        Returns
        -------
        fill_value : int

        Raises
        ------
        ValueError
        rMz'fill_value=z1' is not present in this Categorical's categoriesrQ)r/rXr`rS)rfr�rprprqr��s
z Categorical._validate_fill_valuecCsFt|jj|j�}|r0t||jj�r0tj||�St|�rBtj|�}|S)z�
        The numpy array interface.

        Returns
        -------
        numpy.array
            A numpy array of either the specified dtype or,
            if dtype==None (default), the same dtype as
            categorical.categories.dtype.
        )	r6rXr�r]r"rPrar�r#)rfrPrkrprprq�	__array__�s
zCategorical.__array__cOs>tj|||f|�|�}|tk	r"|Std|j�d|j����dS)NzObject with dtype z cannot perform the numpy op )r1Z!maybe_dispatch_ufunc_to_dunder_op�NotImplementedrUrPrs)rfZufunc�method�inputs�kwargs�resultrprprq�__array_ufunc__�szCategorical.__array_ufunc__cCsVt|t�std��d|kr0t|d|d�|d<x |j�D]\}}t|||�q:WdS)z*Necessary for making this object picklablezinvalid pickle stater�Z_categoriesZ_orderedN)rV�dict�	Exceptionr*�items�setattr)rf�state�kr�rprprq�__setstate__�s
zCategorical.__setstate__cCs|jj|jjjjS)N)r]�nbytesrPrXr�)rfrprprqr�szCategorical.nbytescCs|jj|jjj|d�S)a�
        Memory usage of my values

        Parameters
        ----------
        deep : bool
            Introspect the data deeply, interrogate
            `object` dtypes for system-level memory consumption

        Returns
        -------
        bytes used

        Notes
        -----
        Memory usage does not include memory consumed by elements that
        are not components of the array if deep=False

        See Also
        --------
        numpy.ndarray.nbytes
        )�deep)r]r�rPrX�memory_usage)rfr�rprprqr�szCategorical.memory_usage�searchsorted)�klass�leftcsZt|�r$�jj|�}�jjj|�}n$�fdd�|D�}tj|�jjd�}�jj|||d�S)Ncsg|]}�jj|��qSrp)rXr`)rur�)rfrprqr�-sz,Categorical.searchsorted.<locals>.<listcomp>)rP)�side�sorter)	r'rXr`r�rPrerar?r�)rfr�r�r�r�Zlocsrp)rfrqr�%szCategorical.searchsortedcCs|jdk}|S)aW
        Detect missing values

        Missing values (-1 in .codes) are detected.

        Returns
        -------
        a boolean array of whether my values are null

        See Also
        --------
        isna : Top-level isna.
        isnull : Alias of isna.
        Categorical.notna : Boolean inverse of Categorical.isna.

        rMrQ)r])rfrkrprprqr/1s
zCategorical.isnacCs
|j�S)a�
        Inverse of isna

        Both missing values (-1 in .codes) and NA as a category are detected as
        null.

        Returns
        -------
        a boolean array of whether my values are not null

        See Also
        --------
        notna : Top-level notna.
        notnull : Alias of notna.
        Categorical.isna : Boolean inverse of Categorical.notna.

        )r/)rfrprprqr0GszCategorical.notnacCs||j�}|S)z�
        Return the Categorical without null values.

        Missing values (-1 in .codes) are detected.

        Returns
        -------
        valid : Categorical
        )r0)rfr�rprprq�dropna]s
zCategorical.dropnacCs�ddlm}m}|j|j}}t|�d|k}}tj|�|j�}}	|sL|	rp|	rT|n||}
tj	|
|phdd�}n tj	tj
|||��}tj|d	�}|j||j
dd�}||||�dd�S)
a{
        Return a Series containing counts of each category.

        Every category will have an entry, even those with a count of 0.

        Parameters
        ----------
        dropna : bool, default True
            Don't include counts of NaN.

        Returns
        -------
        counts : Series

        See Also
        --------
        Series.value_counts
        r)�CategoricalIndex�Series)Z	minlengthrMT)rPr�r�)�indexrPrQ)r�r�r�r]rXrRra�arangerYZbincountr��appendr�rP)rfr�r�r��coderzZncatrl�ix�cleanZobs�countrprprq�value_countskszCategorical.value_countscCsVt|jj�r|jj|jtd�St|j�rLd|jkrL|jjd�j|jtj	d�Stj
|�S)a
        Return the values.

        For internal compatibility with pandas formatting.

        Returns
        -------
        np.ndarray or Index
            A numpy array of the same dtype as categorical.categories.dtype or
            Index if datetime / periods.
        )r�rM�objectrQ)r)rXrPr�r]r
r$r�rar�r?)rfrprprq�_internal_get_values�s

z Categorical._internal_get_valuescCs|jstd|�d���dS)z assert that we are ordered z)Categorical is not ordered for operation zG
you can use .as_ordered() to change the Categorical to an ordered one
N)rTrU)rfrnrprprq�check_for_ordered�szCategorical.check_for_orderedcCs|jS)N)r])rfrprprq�_values_for_argsort�szCategorical._values_for_argsort�	quicksortcst�jf||d�|��S)a�
        Return the indices that would sort the Categorical.

        .. versionchanged:: 0.25.0

           Changed to sort missing values at the end.

        Parameters
        ----------
        ascending : bool, default True
            Whether the indices should result in an ascending
            or descending sort.
        kind : {'quicksort', 'mergesort', 'heapsort'}, optional
            Sorting algorithm.
        **kwargs:
            passed through to :func:`numpy.argsort`.

        Returns
        -------
        numpy.array

        See Also
        --------
        numpy.ndarray.argsort

        Notes
        -----
        While an ordering is applied to the category values, arg-sorting
        in this context refers more to organizing and grouping together
        based on matching category values. Thus, this function can be
        called on an unordered Categorical instance unlike the functions
        'Categorical.min' and 'Categorical.max'.

        Examples
        --------
        >>> pd.Categorical(['b', 'b', 'a', 'c']).argsort()
        array([2, 0, 1, 3])

        >>> cat = pd.Categorical(['b', 'b', 'a', 'c'],
        ...                      categories=['c', 'b', 'a'],
        ...                      ordered=True)
        >>> cat.argsort()
        array([3, 0, 1, 2])

        Missing values are placed at the end

        >>> cat = pd.Categorical([2, None, 1])
        >>> cat.argsort()
        array([2, 0, 1])
        )�	ascending�kind)�super�argsort)rfr�r�r�)�	__class__rprqr��s3zCategorical.argsort�last)r�r��na_positioncCs`t|d�}|d	kr$tdt|�����t|||d�}|rD|j||_n|j|j||jdd�SdS)
a7	
        Sort the Categorical by category value returning a new
        Categorical by default.

        While an ordering is applied to the category values, sorting in this
        context refers more to organizing and grouping together based on
        matching category values. Thus, this function can be called on an
        unordered Categorical instance unlike the functions 'Categorical.min'
        and 'Categorical.max'.

        Parameters
        ----------
        inplace : bool, default False
            Do operation in place.
        ascending : bool, default True
            Order ascending. Passing False orders descending. The
            ordering parameter provides the method by which the
            category values are organized.
        na_position : {'first', 'last'} (optional, default='last')
            'first' puts NaNs at the beginning
            'last' puts NaNs at the end

        Returns
        -------
        Categorical or None

        See Also
        --------
        Categorical.sort
        Series.sort_values

        Examples
        --------
        >>> c = pd.Categorical([1, 2, 2, 1, 5])
        >>> c
        [1, 2, 2, 1, 5]
        Categories (3, int64): [1, 2, 5]
        >>> c.sort_values()
        [1, 1, 2, 2, 5]
        Categories (3, int64): [1, 2, 5]
        >>> c.sort_values(ascending=False)
        [5, 2, 2, 1, 1]
        Categories (3, int64): [1, 2, 5]

        Inplace sorting can be done as well:

        >>> c.sort_values(inplace=True)
        >>> c
        [1, 1, 2, 2, 5]
        Categories (3, int64): [1, 2, 5]
        >>>
        >>> c = pd.Categorical([1, 2, 2, 1, 5])

        'sort_values' behaviour with NaNs. Note that 'na_position'
        is independent of the 'ascending' parameter:

        >>> c = pd.Categorical([np.nan, 2, 2, np.nan, 5])
        >>> c
        [NaN, 2, 2, NaN, 5]
        Categories (2, int64): [2, 5]
        >>> c.sort_values()
        [2, 2, 5, NaN, NaN]
        Categories (2, int64): [2, 5]
        >>> c.sort_values(ascending=False)
        [5, 2, 2, NaN, NaN]
        Categories (2, int64): [2, 5]
        >>> c.sort_values(na_position='first')
        [NaN, NaN, 2, 2, 5]
        Categories (2, int64): [2, 5]
        >>> c.sort_values(ascending=False, na_position='first')
        [NaN, NaN, 5, 2, 2]
        Categories (2, int64): [2, 5]
        r�r�firstzinvalid na_position: )r�rT)r�rPr�N)rr)rrS�reprrFr]r�rP)rfr�r�rZ
sorted_idxrprprqr��sL
zCategorical.sort_valuescCstddlm}|jr>|j}|dk}|j�rp|jd�}tj||<n2|jj	�rTtj
|�}ntj
|j||j�j�j
��}|S)z�
        For correctly ranking ordered categorical data. See GH#15420

        Ordered categorical data should be ranked on the basis of
        codes with -1 translated to NaN.

        Returns
        -------
        numpy.array

        r)r�rMZfloat64rQ)r�r�rTr�r_r�rar�rXr�r?r�Zrankr�)rfr�r�rlrprprq�_values_for_rank<s

zCategorical._values_for_rankcCs$|dk	rt|��|j|j|jdd�S)NT)r�rPr�)r�r�r]rP)rfrPrprprqr�ZszCategorical.viewcCstdtdd�tj|�S)z�
        Return my 'dense' representation

        For internal compatibility with numpy arrays.

        Returns
        -------
        dense : array
        ziCategorical.to_dense is deprecated and will be removed in a future version.  Use np.asarray(cat) instead.�)�
stacklevel)r�
FutureWarningrar�)rfrprprq�to_dense_s

zCategorical.to_densec	Cszt||dd�\}}|dkr tj}|dk	r0td��|j}|dk	r�tj|�jdt|��}t||dd|�j	|j
j�d}t||j
�}n�t
|tjttf�r�tj||j
�}t||�j�s�td��t||j
�}tj|dk�}|j�}||||<n~t|��rTt|��r||j
k�rtd��|d
k}|j��rh|j�}t|��rBd||<n|j
j|�||<ntdt|�j����|j||jd	d
�S)a(
        Fill NA/NaN values using the specified method.

        Parameters
        ----------
        value : scalar, dict, Series
            If a scalar value is passed it is used to fill all missing values.
            Alternatively, a Series or dict can be used to fill in different
            values for each index. The value should not be a list. The
            value(s) passed should either be in the categories or should be
            NaN.
        method : {'backfill', 'bfill', 'pad', 'ffill', None}, default None
            Method to use for filling holes in reindexed Series
            pad / ffill: propagate last valid observation forward to next valid
            backfill / bfill: use NEXT valid observation to fill gap
        limit : int, default None
            (Not implemented yet for Categorical!)
            If method is specified, this is the maximum number of consecutive
            NaN values to forward/backward fill. In other words, if there is
            a gap with more than this number of consecutive NaNs, it will only
            be partially filled. If method is not specified, this is the
            maximum number of entries along the entire axis where NaNs will be
            filled.

        Returns
        -------
        filled : Categorical with NA/NaN filled
        F)Zvalidate_scalar_dict_valueNz:specifying a limit for fillna has not been implemented yetrMrz fill value must be in categorieszE'value' parameter must be a scalar, dict or Series, but you passed a T)rPr�rQrQrQrQ)rrar�r�r]r�ZreshaperRrDr�rXrPr\rVr�rWr,�
algorithmsr�r/rYrSr�r�r-r_r`rUrersr�)	rfr�r��limitr�r�rlZvalues_codes�indexerrprprq�fillnaqsD



zCategorical.fillna)rf�
allow_fillr�cCstj||||d�S)a	
        Take elements from the Categorical.

        Parameters
        ----------
        indexer : sequence of int
            The indices in `self` to take. The meaning of negative values in
            `indexer` depends on the value of `allow_fill`.
        allow_fill : bool, default False
            How to handle negative values in `indexer`.

            * False: negative values in `indices` indicate positional indices
              from the right. This is similar to
              :func:`numpy.take`.

            * True: negative values in `indices` indicate missing values
              (the default). These values are set to `fill_value`. Any other
              other negative values raise a ``ValueError``.

            .. versionchanged:: 1.0.0

               Default value changed from ``True`` to ``False``.

        fill_value : object
            The value to use for `indices` that are missing (-1), when
            ``allow_fill=True``. This should be the category, i.e. a value
            in ``self.categories``, not a code.

        Returns
        -------
        Categorical
            This Categorical will have the same categories and ordered as
            `self`.

        See Also
        --------
        Series.take : Similar method for Series.
        numpy.ndarray.take : Similar method for NumPy arrays.

        Examples
        --------
        >>> cat = pd.Categorical(['a', 'a', 'b'])
        >>> cat
        ['a', 'a', 'b']
        Categories (2, object): ['a', 'b']

        Specify ``allow_fill==False`` to have negative indices mean indexing
        from the right.

        >>> cat.take([0, -1, -2], allow_fill=False)
        ['a', 'b', 'a']
        Categories (2, object): ['a', 'b']

        With ``allow_fill=True``, indices equal to ``-1`` mean "missing"
        values that should be filled with the `fill_value`, which is
        ``np.nan`` by default.

        >>> cat.take([0, -1, -1], allow_fill=True)
        ['a', NaN, NaN]
        Categories (2, object): ['a', 'b']

        The fill value can be specified.

        >>> cat.take([0, -1, -1], allow_fill=True, fill_value='a')
        ['a', 'a', 'a']
        Categories (2, object): ['a', 'b']

        Specifying a fill value that's not in ``self.categories``
        will raise a ``ValueError``.
        )r
r�)r:r�)rfrr
r�rprprqr��sGzCategorical.takecCs|jS)N)r])rfrprprq�_ndarrayszCategorical._ndarray)�arrr�cCs|j||jdd�S)NT)rPr�)r�rP)rfrrprprq�_from_backing_dataszCategorical._from_backing_data)r
cCstdtdd�|j|||d�S)Nz?Categorical.take_nd is deprecated, use Categorical.take insteadr)r)r
r�)rrr�)rfrr
r�rprprq�take_nd"s
zCategorical.take_ndcCst|j�j��S)zJ
        Returns an Iterator over the values of this Categorical.
        )�iterr�r~)rfrprprq�__iter__+szCategorical.__iter__cCs*t||jj�r|j�j�St|||jd�S)z?
        Returns True if `key` is in this Categorical.
        )rv)r.rXrPr/r_r}r])rfr{rprprq�__contains__1szCategorical.__contains__�
cCsv|d}|d|�jddd�}|||d�jddd�}|dd��d|dd���}|rn|�d|j���}t|�S)	zd
        a short repr displaying only max_vals and an optional (but default
        footer)
        rNF)�length�footerrMz, ..., �
rQ)�	_get_repr�_repr_footerr�)rfZmax_valsr�num�head�tailr�rprprq�
_tidy_repr;szCategorical._tidy_reprcCs�td�dkrdntd�}ddlm}t|jdtd�}t|j�|kr�|d}||jd|��}||j|d��}|dg|}n
||j�}d	d
�|D�}|S)z9
        return the base repr for the categories
        zdisplay.max_categoriesrr)�formatN)�	formatter�quotingrz...cSsg|]}|j��qSrp)�strip)rur�rprprqr�asz0Categorical._repr_categories.<locals>.<listcomp>)r�pandas.io.formatsrr�format_arrayrrRrX)rfZmax_categories�fmtr$rrr�
category_strsrprprq�_repr_categoriesJs
zCategorical._repr_categoriescCs|j�}t|jj�}dt|j��d|�d�}t�\}}td�p@|}tj�rNd}d}d}t|�}	|j	rhdnd\}
}|j
�d}xr|D]j}
|dkr�|	|
t|
�|kr�||dt|�d
7}t|�d
}	n|s�||7}|	t|
�7}	||
7}d}q�W|d|jdd�dS)z@
        Returns a string representation of the footer.
        zCategories (�, z): z
display.widthr�T�� < rr� rMF�[z	 < ... < z ... �])r*r+)rr()r'r�rXrPrRrrrGZin_ipython_frontendrT�rstrip�replace)rfr&rPZ	levheader�width�height�	max_widthZ	levstring�startZcur_col_lenZsep_len�sep�linesep�valrprprq�_repr_categories_infods,

z!Categorical._repr_categories_infocCs|j�}dt|��d|��S)NzLength: r)r8rR)rf�inforprprqr�szCategorical._repr_footer�NaNcCs.ddlm}|j||||d�}|j�}t|�S)Nr)r)r�na_repr)r#rZCategoricalFormatterZ	to_stringr�)rfrr;rr%r r�rprprqr�s
zCategorical._get_reprcCsfd}t|j�|kr|j|�}nDt|j�dkrB|jt|�|kd�}n |jddd�jdd�}d	|��}|S)
z(
        String representation.
        rr)rFT)rrrz, z[], )rRr]rrr0)rf�_maxlenr�rhrprprq�__repr__�s
zCategorical.__repr__cCs*t|tj�r&|jjdkr&|j|jj�}|S)z>
        return an indexer coerced to the codes dtype
        rm)rVrar�rPr�r�r])rfrrprprq�_maybe_coerce_indexer�sz!Categorical._maybe_coerce_indexercCsnt|ttjf�r2|j|}|dkr(tjS|j|St||�}|j|}|jdkr\t	|�|S|j
||jdd�S)z!
        Return an item.
        rMT)rPr�rQ)rV�intra�integerr]r�rXrBr�rCr�rP)rfr{rmr�rprprq�__getitem__�s




zCategorical.__getitem__cCsJt|dd�}t|t�rXt||�s(td��|jj|j�sXt|j|j|j�}tj	||j
d�}t|�rd|n|g}ddlm
}||�j|j�}t|�r�t|�j�r�td��t|ttjf�r�nft|t��rt|�dkr�tj|d�s�td	��|d
}n t|�d
k�r|d}ntd	��nt|t��r|jj|�}|j|�}t||�}||j|<dS)z�
        Item assignment.

        Raises
        ------
        ValueError
            If (one or more) Value is not in categories or if a assigned
            `Categorical` does not have the same categories
        T)Z
extract_numpyzCCannot set a Categorical with another, without identical categories)rPr)r�zMCannot setitem on a Categorical with a new category, set the categories firstrz(invalid slicing for a 1-ndim categoricalrMN)r@rVrWr"rSrXr[r�r�r�rPr%r�r��
differencerRr/rYr?rar@�tupler�Z
is_null_slice�AssertionError�slice�get_indexerr>rBr])rfr{r��	new_codesZrvaluer�Zto_addZlindexerrprprq�__setitem__�s<







zCategorical.__setitem__csZ|j}tj|jjd�|j�\�}|j�}�fdd�t||dd��D�}tt||��}|S)aw
        Compute the inverse of a categorical, returning
        a dict of categories -> indexers.

        *This is an internal function*

        Returns
        -------
        dict of categories -> indexers

        Examples
        --------
        >>> c = pd.Categorical(list('aabca'))
        >>> c
        ['a', 'a', 'b', 'c', 'a']
        Categories (3, object): ['a', 'b', 'c']
        >>> c.categories
        Index(['a', 'b', 'c'], dtype='object')
        >>> c.codes
        array([0, 0, 1, 2, 0], dtype=int8)
        >>> c._reverse_indexer()
        {'a': array([0, 1, 4]), 'b': array([2]), 'c': array([3])}

        r�c3s|]\}}�||�VqdS)Nrp)rur4�end)�rrprqrwsz/Categorical._reverse_indexer.<locals>.<genexpr>rMN)	rX�libalgosZgroupsort_indexerr�r�r�Zcumsum�zipr�)rfrX�countsZ_resultr�rp)rJrq�_reverse_indexer�s zCategorical._reverse_indexer)�name�skipnacKs4t||d�}|dkr"td|����|fd|i|��S)Nz)Categorical cannot perform the operation rP)r^rU)rfrOrPr�rrrprprq�_reduceszCategorical._reduceZnumeric_onlyrP)Zold_arg_nameZnew_arg_namecKsrtjf|�|jd�t|j�s(|jjS|jdk}|j�s^|rV|j�rV|j|j	�}qht
jSn
|jj	�}|j|S)ao
        The minimum value of the object.

        Only ordered `Categoricals` have a minimum!

        .. versionchanged:: 1.0.0

           Returns an NA value on empty arrays

        Raises
        ------
        TypeError
            If the `Categorical` is not `ordered`.

        Returns
        -------
        min : the minimum of this `Categorical`
        r�rMrQ)
�nvZvalidate_minr�rRr]rP�na_valuerYr_r�rar�rX)rfrPr��good�pointerrprprqr�%s



zCategorical.mincKsrtjf|�|jd�t|j�s(|jjS|jdk}|j�s^|rV|j�rV|j|j	�}qht
jSn
|jj	�}|j|S)ao
        The maximum value of the object.

        Only ordered `Categoricals` have a maximum!

        .. versionchanged:: 1.0.0

           Returns an NA value on empty arrays

        Raises
        ------
        TypeError
            If the `Categorical` is not `ordered`.

        Returns
        -------
        max : the maximum of this `Categorical`
        r�rMrQ)
rRZvalidate_maxr�rRr]rPrSrYr_r�rar�rX)rfrPr�rTrUrprprqr�Is



zCategorical.maxcCsD|j}|r|jdk}|j|}ttjt|�|��}|j||jdd�S)a^
        Returns the mode(s) of the Categorical.

        Always returns `Categorical` even if only one value.

        Parameters
        ----------
        dropna : bool, default True
            Don't consider counts of NaN/NaT.

            .. versionadded:: 0.24.0

        Returns
        -------
        modes : `Categorical` (sorted)
        rMT)r�rPr�rQ)r]�sorted�htableZ
mode_int64rr�rP)rfr�r�rTrprprq�modems

zCategorical.modecCsFt|j�}|j�}||_||dk}|jr4tj|�}|j|jj	|��S)a�
        Return the ``Categorical`` which ``categories`` and ``codes`` are
        unique. Unused categories are NOT returned.

        - unordered category: values and categories are sorted by appearance
          order.
        - ordered category: values are sorted by appearance order, categories
          keeps existing order.

        Returns
        -------
        unique values : ``Categorical``

        See Also
        --------
        pandas.unique
        CategoricalIndex.unique
        Series.unique

        Examples
        --------
        An unordered Categorical will return categories in the
        order of appearance.

        >>> pd.Categorical(list("baabc")).unique()
        ['b', 'a', 'c']
        Categories (3, object): ['b', 'a', 'c']

        >>> pd.Categorical(list("baabc"), categories=list("abc")).unique()
        ['b', 'a', 'c']
        Categories (3, object): ['b', 'a', 'c']

        An ordered Categorical preserves the category ordering.

        >>> pd.Categorical(
        ...     list("baabc"), categories=list("abc"), ordered=True
        ... ).unique()
        ['b', 'a', 'c']
        Categories (3, object): ['a' < 'b' < 'c']
        rMrQ)
r7r�r�r]rTrar�r�rXr�)rfZunique_codesrzZ
take_codesrprprqr��s*

zCategorical.uniquecCs|jjd�}|dfS)Nr�rMrQ)r�r�)rfr�rprprq�_values_for_factorize�sz!Categorical._values_for_factorizecCs|j|jj|�|jd�S)N)rP)r�rXr�rP)r�Zuniques�originalrprprq�_from_factorized�szCategorical._from_factorizedcCsD|j|�r@|jj|j�r |j}nt|j|j|j�}tj|j|�SdS)z�
        Returns True if categorical arrays are equal.

        Parameters
        ----------
        other : `Categorical`

        Returns
        -------
        bool
        F)r"rXr[r]r�r�raZarray_equal)rfrgrirprprqr[�s
zCategorical.equalscCs2yt|j�t|j�kSttfk
r,dSXdS)z�
        Returns True if categoricals are the same dtype
          same categories, and same ordered

        Parameters
        ----------
        other : Categorical

        Returns
        -------
        bool
        FN)rxrP�AttributeErrorrU)rfrgrprprqr"�s
zCategorical.is_dtype_equalcCsN|jdd�}|t|j��}ddlm}|||gdd�}ddg|_d	|j_|S)
z�
        Describes this Categorical

        Returns
        -------
        description: `DataFrame`
            A dataframe with frequency and counts by category.
        F)r�r)�concatrM)r�rM�freqsrX)r��float�sumZpandas.core.reshape.concatr]�columnsr�rO)rfrMr^r]r�rprprq�describe�s	
zCategorical.describecCsdS)NTrp)rfrprprq�_can_hold_na	szCategorical._can_hold_nacCsddlm}||�S)Nr)�union_categoricals)Zpandas.core.dtypes.concatrd)rfZ	to_concatrdrprprq�_concat_same_type	szCategorical._concat_same_typecCsft|�s"t|�j}td|�d���t|dd�}tjt|��}|jj	|�}|||dkB}t
j|j|�S)a�
        Check whether `values` are contained in Categorical.

        Return a boolean NumPy Array showing whether each element in
        the Categorical matches an element in the passed sequence of
        `values` exactly.

        Parameters
        ----------
        values : set or list-like
            The sequence of values to test. Passing in a single string will
            raise a ``TypeError``. Instead, turn a single string into a
            list of one element.

        Returns
        -------
        isin : numpy.ndarray (bool dtype)

        Raises
        ------
        TypeError
          * If `values` is not a set or list-like

        See Also
        --------
        pandas.Series.isin : Equivalent method on Series.

        Examples
        --------
        >>> s = pd.Categorical(['lama', 'cow', 'lama', 'beetle', 'lama',
        ...                'hippo'])
        >>> s.isin(['cow', 'lama'])
        array([ True,  True,  True, False,  True, False])

        Passing a single string as ``s.isin('lama')`` will raise an error. Use
        a list of one element instead:

        >>> s.isin(['lama'])
        array([ True, False,  True, False,  True, False])
        zIonly list-like objects are allowed to be passed to isin(), you passed a [r.Nr)
r%rersrUrArar�r/rXrFr	r�r�)rfr�Zvalues_typer�Zcode_valuesrprprqr�
	s)
zCategorical.isin)r�cs�t|d�}|r|n|j�}t|�r6�fdd�|D�}n|�i}x�|j�D]�\}}||krZqH||jkrHt|�r||j|dd�qH|jj�}|j|�}	||jkr�|j|�}
|
|j	|j	|	k<|j|dd�qH|||	<|j
|dd�qHW|s�|SdS)aM
        Replaces all instances of one value with another

        Parameters
        ----------
        to_replace: object
            The value to be replaced

        value: object
            The value to replace it with

        inplace: bool
            Whether the operation is done in-place

        Returns
        -------
        None if inplace is True, otherwise the new Categorical after replacement


        Examples
        --------
        >>> s = pd.Categorical([1, 2, 1, 3])
        >>> s.replace(1, 3)
        [3, 2, 3, 3]
        Categories (2, int64): [2, 3]
        r�csi|]
}�|�qSrprp)ru�
replace_value)r�rprq�
<dictcomp>c	sz'Categorical.replace.<locals>.<dictcomp>T)r�N)rr�r%r�rXr/r�r~r�r]r�)rfZ
to_replacer�r�rzZreplace_dictrfZ	new_valuerXr�Zvalue_indexrp)r�rqr0B	s,





zCategorical.replace)NNNF)NF)F)T)N)NNN)F)F)F)F)NFF)F)NF)F)F)F)N)N)F)r�N)T)Tr�)FTr)N)NNN)FN)FN)rT)Tr:T)T)T)T)T)F)~rs�
__module__�__qualname__�__doc__Z__array_priority__r*r�r=Z
_deprecations�	frozensetZ_typr��propertyrX�setterrrTrPrr��classmethodr�r�rrcrr�rr?r�rrr~Zto_listr�r�rar�r�r�r�r�r�r�r�r�r�r�r�r�r�rt�operator�eqrO�nerN�ltrI�gtrJ�lerK�gerLr8r�r�r�r�r�r�rr>r�r/Zisnullr0Znotnullr�r�r�r�r�r�r�r�rr�rrr9r�rrrrrrr'r8rrr=r>rArHrrrNrQrr�r�rXr�rYr[r[r"rbrcrer�r0�
__classcell__rprp)r�rqrW�s�Y

P

<E
%



I
O
+
2
4
'Q








$	6X

ZN	
	D#
#
#
65rWrXrTrl)ZdelegateZ	accessors�typr�r�r�r�r�r�r�r�r�c@sHeZdZdZdd�Zedd��Zdd�Zdd	�Ze	d
d��Z
dd
�ZdS)�CategoricalAccessora
    Accessor object for categorical properties of the Series values.

    Be aware that assigning to `categories` is a inplace operation, while all
    methods return new categorical data per default (but can be called with
    `inplace=True`).

    Parameters
    ----------
    data : Series or CategoricalIndex

    Examples
    --------
    >>> s = pd.Series(list("abbccc")).astype("category")
    >>> s
    0    a
    1    b
    2    b
    3    c
    4    c
    5    c
    dtype: category
    Categories (3, object): ['a', 'b', 'c']

    >>> s.cat.categories
    Index(['a', 'b', 'c'], dtype='object')

    >>> s.cat.rename_categories(list("cba"))
    0    c
    1    b
    2    b
    3    a
    4    a
    5    a
    dtype: category
    Categories (3, object): ['c', 'b', 'a']

    >>> s.cat.reorder_categories(list("cba"))
    0    a
    1    b
    2    b
    3    c
    4    c
    5    c
    dtype: category
    Categories (3, object): ['c', 'b', 'a']

    >>> s.cat.add_categories(["d", "e"])
    0    a
    1    b
    2    b
    3    c
    4    c
    5    c
    dtype: category
    Categories (5, object): ['a', 'b', 'c', 'd', 'e']

    >>> s.cat.remove_categories(["a", "c"])
    0    NaN
    1      b
    2      b
    3    NaN
    4    NaN
    5    NaN
    dtype: category
    Categories (1, object): ['b']

    >>> s1 = s.cat.add_categories(["d", "e"])
    >>> s1.cat.remove_unused_categories()
    0    a
    1    b
    2    b
    3    c
    4    c
    5    c
    dtype: category
    Categories (3, object): ['a', 'b', 'c']

    >>> s.cat.set_categories(list("abcde"))
    0    a
    1    b
    2    b
    3    c
    4    c
    5    c
    dtype: category
    Categories (5, object): ['a', 'b', 'c', 'd', 'e']

    >>> s.cat.as_ordered()
    0    a
    1    b
    2    b
    3    c
    4    c
    5    c
    dtype: category
    Categories (3, object): ['a' < 'b' < 'c']

    >>> s.cat.as_unordered()
    0    a
    1    b
    2    b
    3    c
    4    c
    5    c
    dtype: category
    Categories (3, object): ['a', 'b', 'c']
    cCs.|j|�|j|_|j|_|j|_|j�dS)N)�	_validater��_parentr��_indexrO�_nameZ_freeze)rf�datarprprqr�
s

zCategoricalAccessor.__init__cCst|j�std��dS)Nz2Can only use .cat accessor with a 'category' dtype)rrPr\)r}rprprqry
s
zCategoricalAccessor._validatecCst|j|�S)N)r^rz)rfrOrprprq�_delegate_property_get
sz*CategoricalAccessor._delegate_property_getcCst|j||�S)N)r�rz)rfrOZ
new_valuesrprprq�_delegate_property_set
sz*CategoricalAccessor._delegate_property_setcCsddlm}||jj|jd�S)z>
        Return Series of codes as well as the index.
        r)r�)r�)r�r�rzr�r{)rfr�rprprqr�
szCategoricalAccessor.codescOs@ddlm}t|j|�}|||�}|dk	r<|||j|jd�SdS)Nr)r�)r�rO)r�r�r^rzr{r|)rfrO�argsr�r�r��resrprprq�_delegate_method
s

z$CategoricalAccessor._delegate_methodN)rsrhrirjr��staticmethodryr~rrlr�r�rprprprqrx�	s}	rxc	Cs�t|j|j�}t|j�rPt|�rP|jj�}t||�}t||�sdt|�}t|�}n|sdt|�}t|�}t|t�r~t	|j
|�|�St|�\}}t|�\}}|t|��}|j
|�t	|j|�|�S)zR
    utility routine to turn values into codes given the specified categories
    )r"rPr#r&Zconstruct_array_typerrVrr+rZget_indexer_forr4rRZ
map_locations�lookup)	r�rXZdtype_equalr�Z
hash_klass�vals�_r��trprprqr\'
s"





r\)r�cCsLt|�dkr|j�S|j|�r&|j�St|j|�|�}t||j�dd�}|S)a�
    Convert a set of codes for to a new set of categories

    Parameters
    ----------
    codes : np.ndarray
    old_categories, new_categories : Index

    Returns
    -------
    new_codes : np.ndarray[np.int64]

    Examples
    --------
    >>> old_cat = pd.Index(['b', 'a', 'c'])
    >>> new_cat = pd.Index(['a', 'b'])
    >>> codes = np.array([0, 1, 1, 2])
    >>> recode_for_categories(codes, old_cat, new_cat)
    array([ 1,  0,  0, -1], dtype=int8)
    rrM)r�rQ)rRr�r[rrFr6)r�Zold_categoriesr�rrGrprprqr�G
s
r�cCspt|�std��t|�rPt|�}tjt|j�|jj	d�}t
j||j	d�}|j}nt
|dd�}|j}|j}||fS)a�
    Factorize an input `values` into `categories` and `codes`. Preserves
    categorical dtype in `categories`.

    *This is an internal function*

    Parameters
    ----------
    values : list-like

    Returns
    -------
    codes : ndarray
    categories : Index
        If `values` has a categorical dtype, then `categories` is
        a CategoricalIndex keeping the categories and order of `values`.
    zInput must be list-like)rPF)rT)r%rUrr@rar�rRrXr�rPrWr�)r�Z	cat_codesrXr�rzrprprq�factorize_from_iterablei
sr�cCs,t|�dkrgggStttdd�|D���S)aR
    A higher-level wrapper over `factorize_from_iterable`.

    *This is an internal function*

    Parameters
    ----------
    iterables : list-like of list-likes

    Returns
    -------
    codes_list : list of ndarrays
    categories_list : list of Indexes

    Notes
    -----
    See `factorize_from_iterable` for more info.
    rcss|]}t|�VqdS)N)r�)ru�itrprprqrw�
sz+factorize_from_iterables.<locals>.<genexpr>)rRr�r�rL)�	iterablesrprprq�factorize_from_iterables�
sr�)w�csvr�	functoolsrro�shutilrZtypingrrrrr	r
�warningsrZnumpyraZpandas._configrZpandas._libsr
rrKrrWZpandas._typingrrrrZpandas.compat.numpyrrRZpandas.util._decoratorsrrrZpandas.util._validatorsrrZpandas.core.dtypes.castrrrZpandas.core.dtypes.commonrrrr r!r"r#r$r%r&r'r(r)Zpandas.core.dtypes.dtypesr*Zpandas.core.dtypes.genericr+r,Zpandas.core.dtypes.inferencer-Zpandas.core.dtypes.missingr.r/r0Zpandas.corer1Zpandas.core.accessorr2r3Zpandas.core.algorithms�corer	r4r5r6r7Z"pandas.core.array_algos.transformsr8Zpandas.core.arrays._mixinsr9r:Zpandas.core.baser;r<r=r>Zpandas.core.common�commonr�Zpandas.core.constructionr?r@rAZpandas.core.indexersrBrCZpandas.core.missingrDZpandas.core.ops.commonrEZpandas.core.sortingrFr#rGrtr}rWrxr\r�r�r�r�rprprprq�<module>s� <X3F "&