U
    KvfK<                     @   s   d Z ddlZddlZddlZddlmZ ddl	m
Z
 dd Zd-ddZd.d
dZd/ddZd0ddZdd Zd1ddZdd Zdd Zdd Zd2ddZd d! Zd"d# Zd$d% ZG d&d' d'eZd3d(d)Zd4d+d,ZdS )5z
Utility functions models code
    N)_is_using_pandas)
array_likec                 C   s.   t | tr| S t | tr"| dS t| S d S )Nlatin1)
isinstancestrbytesdecode)s r
   ;/tmp/pip-unpacked-wheel-2v6byqio/statsmodels/tools/tools.pyasstr2   s
    


r   c                 C   s&   i }t | D ]\}}|||| < q|S )zd
    Helper function to create a dictionary mapping a column number
    to the name in tmp_arr.
    )	enumerate)Ztmp_arroffsetZcol_mapiZcol_namer
   r
   r   _make_dictnames   s    r      c                 C   s   t | } | jdkr$| dddf } |dk	rt |}|jdkrP|dddf }t t | | t || }| | || fS t | | }| | S dS )a  
    Returns views on the arrays Y and X where missing observations are dropped.

    Y : array_like
    X : array_like, optional
    axis : int
        Axis along which to look for missing observations.  Default is 1, ie.,
        observations in rows.

    Returns
    -------
    Y : ndarray
        All Y where the
    X : ndarray

    Notes
    -----
    If either Y or X is 1d, it is reshaped to be 2d.
    r   N)npasarrayndimarraylogical_andisnanany)YXaxisZkeepidxr
   r
   r   drop_missing    s    



r   Fc                 C   s   t ddS )ax  
    Construct a dummy matrix from categorical variables

    .. deprecated:: 0.12

       Use pandas.get_dummies instead.

    Parameters
    ----------
    data : array_like
        An array, Series or DataFrame.  This can be either a 1d vector of
        the categorical variable or a 2d array with the column specifying
        the categorical variable specified by the col argument.
    col : {str, int, None}
        If data is a DataFrame col must in a column of data. If data is a
        Series, col must be either the name of the Series or None. For arrays,
        `col` can be an int that is the (zero-based) column index
        number.  `col` can only be None for a 1d array.  The default is None.
    dictnames : bool, optional
        If True, a dictionary mapping the column number to the categorical
        name is returned.  Used to have information about plain arrays.
    drop : bool
        Whether or not keep the categorical variable in the returned matrix.

    Returns
    -------
    dummy_matrix : array_like
        A matrix of dummy (indicator/binary) float variables for the
        categorical data.
    dictnames :  dict[int, str], optional
        Mapping between column numbers and categorical names.

    Notes
    -----
    This returns a dummy variable for *each* distinct variable.  If a
    a DaataFrame is provided, the names for the new variable is the
    old variable name - underscore - category name.  So if the a variable
    'vote' had answers as 'yes' or 'no' then the returned array would have to
    new variables-- 'vote_yes' and 'vote_no'.  There is currently
    no name checking.

    Examples
    --------
    >>> import numpy as np
    >>> import statsmodels.api as sm

    Univariate examples

    >>> import string
    >>> string_var = [string.ascii_lowercase[0:5],
    ...               string.ascii_lowercase[5:10],
    ...               string.ascii_lowercase[10:15],
    ...               string.ascii_lowercase[15:20],
    ...               string.ascii_lowercase[20:25]]
    >>> string_var *= 5
    >>> string_var = np.asarray(sorted(string_var))
    >>> design = sm.tools.categorical(string_var, drop=True)

    Or for a numerical categorical variable

    >>> instr = np.floor(np.arange(10,60, step=2)/10)
    >>> design = sm.tools.categorical(instr, drop=True)

    With a structured array

    >>> num = np.random.randn(25,2)
    >>> struct_ar = np.zeros((25,1),
    ...                      dtype=[('var1', 'f4'),('var2', 'f4'),
    ...                             ('instrument','f4'),('str_instr','a5')])
    >>> struct_ar['var1'] = num[:,0][:,None]
    >>> struct_ar['var2'] = num[:,1][:,None]
    >>> struct_ar['instrument'] = instr[:,None]
    >>> struct_ar['str_instr'] = string_var[:,None]
    >>> design = sm.tools.categorical(struct_ar, col='instrument', drop=True)

    Or

    >>> design2 = sm.tools.categorical(struct_ar, col='str_instr', drop=True)
    zcategorical has been removedN)NotImplementedError)datacolZ	dictnamesZdropr
   r
   r   categoricalG   s    Pr    Tskipc           	      C   s&  t | dr&ddlm} || d||dS t| }|j}|dkrP|dddf }n|jdkrbtdtj|dd	dk}|tj|d
kdd	M }|	 r|dkr|S |dkr|dkrtdn8t
|jd }ddd || D }td| dt|jd |g}|r|n|ddd }t|S )aq  
    Add a column of ones to an array.

    Parameters
    ----------
    data : array_like
        A column-ordered design matrix.
    prepend : bool
        If true, the constant is in the first column.  Else the constant is
        appended (last column).
    has_constant : str {'raise', 'add', 'skip'}
        Behavior if ``data`` already has a constant. The default will return
        data without adding another constant. If 'raise', will raise an
        error if any column has a constant value. Using 'add' will add a
        column of 1s if a constant column is present.

    Returns
    -------
    array_like
        The original values with a constant (column of ones) as the first or
        last column. Returned value type depends on input type.

    Notes
    -----
    When the input is a pandas Series or DataFrame, the added column's name
    is 'const'.
    Nr   )	add_trendc)Ztrendprependhas_constantr      z)Only implemented for 2-dimensional arraysr           r!   raisezdata is constant.,c                 S   s   g | ]}t |qS r
   )r   ).0r#   r
   r
   r   
<listcomp>   s     z add_constant.<locals>.<listcomp>z
Column(s) z are constant.)r   Zstatsmodels.tsa.tsatoolsr"   r   r   r   
ValueErrorZptpallr   ZarangeshapejoinZonesZcolumn_stack)	r   r$   r%   r"   xr   Zis_nonzero_constcolumnscolsr
   r
   r   add_constant   s.    



r5   c                 C   s   t | ddd} t |ddd}| jdkr6| dddf n| } | jd |jd kr`td|jd  t| |g}tj|tj|krd	S d
S )a6  
    True if (Q, P) contrast `c` is estimable for (N, P) design `d`.

    From an Q x P contrast matrix `C` and an N x P design matrix `D`, checks if
    the contrast `C` is estimable by looking at the rank of ``vstack([C,D])``
    and verifying it is the same as the rank of `D`.

    Parameters
    ----------
    c : array_like
        A contrast matrix with shape (Q, P). If 1 dimensional assume shape is
        (1, P).
    d : array_like
        The design matrix, (N, P).

    Returns
    -------
    bool
        True if the contrast `c` is estimable on design `d`.

    Examples
    --------
    >>> d = np.array([[1, 1, 1, 0, 0, 0],
    ...               [0, 0, 0, 1, 1, 1],
    ...               [1, 1, 1, 1, 1, 1]]).T
    >>> isestimable([1, 0, 0], d)
    False
    >>> isestimable([1, -1, 0], d)
    True
    r#   r&   )Zmaxdimdr   r   NzContrast should have %d columnsFT)r   r   r0   r.   r   Zvstacklinalgmatrix_rank)r#   r6   newr
   r
   r   isestimable   s    r;   V瞯<c              	   C   s   t | } |  } t j| d\}}}t |}|jd }|jd }|t j| }t	t
||D ]*}	||	 |krd||	  ||	< qbd||	< qbt t |t |ddt jjf t |}
|
|fS )z}
    Return the pinv of an array X as well as the singular values
    used in computation.

    Code adapted from numpy.
    Fr   r         ?r(   N)r   r   	conjugater8   svdcopyr0   maximumreducerangemindot	transposemultiplycoreZnewaxis)r2   Zrcondur	   ZvtZs_origmncutoffr   resr
   r
   r   pinv_extended   s    




"rN   c                 C   sj   t | } t j| t jd}t | j}| }|| | j| dk@ ||< d| j|  |j|< t j|j|< |S )z
    Reciprocal of an array with entries less than or equal to 0 set to 0.

    Parameters
    ----------
    x : array_like
        The input array.

    Returns
    -------
    ndarray
        The array with 0-filled reciprocals.
    Zdtyper   r=   r   r   Z
zeros_likefloat64r   Zflatnan)r2   outnansposr
   r
   r   recipr  s    
rV   c                 C   sj   t | } t j| t jd}t | j}| }|| | j| dk@ ||< d| j|  |j|< t j|j|< |S )z
    Reciprocal of an array with entries less than 0 set to 0.

    Parameters
    ----------
    x : array_like
        The input array.

    Returns
    -------
    ndarray
        The array with 0-filled reciprocals.
    rO   r   r=   rP   )r2   rS   rT   Znon_zeror
   r
   r   recipr0/  s    
rW   c                    s:   t j d d} fddt |D }t t |S )z
    Erase columns of zeros: can save some time in pseudoinverse.

    Parameters
    ----------
    matrix : ndarray
        The array to clean.

    Returns
    -------
    ndarray
        The cleaned array.
    r&   r   c                    s   g | ]} d d |f qS Nr
   )r+   r   matrixr
   r   r,   V  s     zclean0.<locals>.<listcomp>)r   addrB   Zflatnonzeror   rF   )rZ   Zcolsumvalr
   rY   r   clean0G  s    r]   c                 C   s   |dkrt j| }t jj| dd\}}}t |}|ddd }g }t|D ]}||dd|| f  qNt t |	t j
S )a  
    Return an array whose column span is the same as x.

    Parameters
    ----------
    x : ndarray
        The array to adjust, 2d.
    r : int, optional
        The rank of x. If not provided, determined by `np.linalg.matrix_rank`.

    Returns
    -------
    ndarray
        The array adjusted to have full rank.

    Notes
    -----
    If the rank of x is known it can be specified as r -- no check
    is made to ensure that this really is the rank of x.
    NF)Zfull_matricesr-   )r   r8   r9   r?   ZargsortrC   appendr   rF   ZastyperQ   )r2   rvr6   rI   ordervaluer   r
   r
   r   fullrankZ  s    
rc   c                 C   s   t |}d||< | |S )aW  
    Unsqueeze a collapsed array.

    Parameters
    ----------
    data : ndarray
        The data to unsqueeze.
    axis : int
        The axis to unsqueeze.
    oldshape : tuple[int]
        The original shape before the squeeze or reduce operation.

    Returns
    -------
    ndarray
        The unsqueezed array.

    Examples
    --------
    >>> from numpy import mean
    >>> from numpy.random import standard_normal
    >>> x = standard_normal((3,4,5))
    >>> m = mean(x, axis=1)
    >>> m.shape
    (3, 5)
    >>> m = unsqueeze(m, 1, x.shape)
    >>> m.shape
    (3, 1, 5)
    >>>
    r   )listZreshape)r   r   ZoldshapeZnewshaper
   r
   r   	unsqueeze{  s    re   c                 C   sZ   t t | |dk}t | dkt |}|| }t t | t |}t j||< |S )z
    Returns np.dot(left_matrix, right_matrix) with the convention that
    nan * 0 = 0 and nan * x = nan if x != 0.

    Parameters
    ----------
    A, B : ndarray
    r   )r   rE   r   Z
nan_to_numrR   )ABZshould_be_nan_1Zshould_be_nan_2Zshould_be_nanCr
   r
   r   nan_dot  s    

ri   c                 C   s   t | d| S )z
    Gets raw results back from wrapped results.

    Can be used in plotting functions or other post-estimation type
    routines.
    Z_results)getattr)resultsr
   r
   r   maybe_unwrap_results  s    rl   c                       s    e Zd ZdZ fddZ  ZS )Buncha  
    Returns a dict-like object with keys accessible via attribute lookup.

    Parameters
    ----------
    *args
        Arguments passed to dict constructor, tuples (key, value).
    **kwargs
        Keyword agument passed to dict constructor, key=value.
    c                    s   t t| j|| | | _d S rX   )superrm   __init____dict__)selfargskwargs	__class__r
   r   ro     s    zBunch.__init__)__name__
__module____qualname____doc__ro   __classcell__r
   r
   rt   r   rm     s   
rm   c                 C   s   | dkr| S t | d}| jdkr8|r.| | jfS | dfS n| jdkrJtd|rT| jnd}|rvt| dddf |fS t| |fS dS )a  

    Parameters
    ----------
    x : ndarray, Series, DataFrame or None
        Input to verify dimensions, and to transform as necesary
    ndarray : bool
        Flag indicating whether to always return a NumPy array. Setting False
        will return an pandas DataFrame when the input is a Series or a
        DataFrame.

    Returns
    -------
    out : ndarray, DataFrame or None
        array or DataFrame with 2 dimensiona.  One dimensional arrays are
        returned as nobs by 1. None is returned if x is None.
    names : list of str or None
        list containing variables names when the input is a pandas datatype.
        Returns None if the input is an ndarray.

    Notes
    -----
    Accepts None for simplicity
    Nr&   zx mst be 1 or 2-dimensional.)	r   r   r3   r.   namer   r   pdZ	DataFrame)r2   ZndarrayZ	is_pandasr{   r
   r
   r   
_ensure_2d  s    




r}   qrc                 C   s   t | ddd} |dkrh| ddtj| dkddf } | t| d d } | j|  } tjj| |dd	S |d
krtjj	| dd\}t
t|}|dkr|d | jd  ttj }t||k S tjj| |dS dS )a(  
    Matrix rank calculation using QR or SVD

    Parameters
    ----------
    m : array_like
        A 2-d array-like object to test
    tol : float, optional
        The tolerance to use when testing the matrix rank. If not provided
        an appropriate value is selected.
    method : {"ip", "qr", "svd"}
        The method used. "ip" uses the inner-product of a normalized version
        of m and then computes the rank using NumPy's matrix_rank.
        "qr" uses a QR decomposition and is the default. "svd" defers to
        NumPy's matrix_rank.

    Returns
    -------
    int
        The rank of m.

    Notes
    -----
    When using a QR factorization, the rank is determined by the number of
    elements on the leading diagonal of the R matrix that are above tol
    in absolute value.
    rJ   r&   r7   ipNr   r'   T)tolZ	hermitianr~   r_   )moder   )r   )r   r   r   sqrtsumTr8   r9   scipyr~   absZdiagr0   ZfinfofloatZepsint)rJ   r   methodr_   Zabs_diagr
   r
   r   r9     s    
r9   )r   )Nr   )NFF)Tr!   )r<   )N)F)Nr~   )ry   Znumpyr   Zpandasr|   Zscipy.linalgr   Zstatsmodels.tools.datar   Zstatsmodels.tools.validationr   r   r   r   r    r5   r;   rN   rV   rW   r]   rc   re   ri   rl   dictrm   r}   r9   r
   r
   r
   r   <module>   s,   	

'
T
:*

!$

+