o
    0GfZ                     @  sr  d dl mZ d dlm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lmZ d dlmZ d dlmZmZ d d	lmZ d d
lmZ d dlmZmZmZmZ g dZdLddZdMddZdNddZ			dOdPd$d%Z 	dQd&d'Z!d(d) Z"d*d+ Z#d,d- Z$d.d/ Z%d0d1 Z&d2d3 Z'd4d5 Z(d6d7 Z)d8d9 Z*d:d; Z+d<d= Z,d>d? Z-d@dA Z.dBdC Z/dDdE Z0dFdG Z1dRdJdKZ2dS )S    )annotations)lrangeN)	DataFrame)offsets)	to_offset)Literal)_is_recarray_is_using_pandas)ValueWarning)NDArray)
array_like	bool_likeint_likestring_like)lagmat	lagmat2ds	add_trendduplication_matrixelimination_matrixcommutation_matrixvecvechunvecunvechfreq_to_periodcFskipc                 C  s  t |d}t|ddd}t|ddd}g d}|dkr|  S |d	kr,|d
d }d}n!|dks4|dkrG|d
d }|dkrD|dd }d}n|dkrMd}t| r[ddlm} t|t| d
}|rst| t	j
rnt	| } n
|  } nt| } t| }ttjd|d tjd|d }	t|	}	|dkr|	d
d
df }	d	|v r|rdd }
| |
d}ntjt| dd}|dk}|| d dk@ }|}t|r|dkr
| jdkrd}n#t| jd | }t| t	jr| j}ddd |D }d| d}| d| d}t||dkr|dd
 }|	d
d
dd
f }	|r$dnd }|rDt	j|	| j|d!}	|	| g} t	j| d
d
| dd} | S |	| g} t| d
d
| } | S )"a  
    Add a trend and/or constant to an array.

    Parameters
    ----------
    x : array_like
        Original array of data.
    trend : str {'n', 'c', 't', 'ct', 'ctt'}
        The trend to add.

        * 'n' add no trend.
        * 'c' add constant only.
        * 't' add trend only.
        * 'ct' add constant and linear trend.
        * 'ctt' add constant and linear and quadratic trend.
    prepend : bool
        If True, prepends the new data to the columns of X.
    has_constant : str {'raise', 'add', 'skip'}
        Controls what happens when trend is 'c' and a constant column already
        exists in x. 'raise' will raise an error. 'add' will add a column of
        1s. 'skip' will return the data without change. 'skip' is the default.

    Returns
    -------
    array_like
        The original data with the additional trend columns.  If x is a
        pandas Series or DataFrame, then the trend column names are 'const',
        'trend' and 'trend_squared'.

    See Also
    --------
    statsmodels.tools.tools.add_constant
        Add a constant column to an array.

    Notes
    -----
    Returns columns as ['ctt','ct','c'] whenever applicable. There is currently
    no checking for an existing trend.
    prependtrend)nr   tctcttoptionshas_constant)raiseaddr   )constr   Ztrend_squaredr   r   N   r   r!   r       r"   )recarray_exception)dtypec                 S  s,   zt | dkot | dkW S    Y dS )Ng        F)npptpany)s r1   8lib/python3.10/site-packages/statsmodels/tsa/tsatools.pysafe_is_const~   s   z add_trend.<locals>.safe_is_constaxisr&   zx is constant.z, c                 S     g | ]}t |qS r1   str.0r   r1   r1   r2   
<listcomp>       zadd_trend.<locals>.<listcomp>z3x contains one or more constant columns. Column(s) z are constant.z Adding a constant with trend='z' is not allowed.r   indexcolumns)r   r   copyr   statsmodels.tools.sm_exceptionsr+   NotImplementedErrorr	   
isinstancepdZSeriesr   r-   
asanyarraylenvanderarangeZfloat64ZfliplrZapplyr.   r/   ndimshaper@   join
ValueErrorr?   concatcolumn_stack)xr   r   r%   r@   Z
trendorderr+   	is_pandasnobsZtrendarrr3   Z	col_constZptp0Zcol_is_constZnz_constZbase_errZ
const_colsmsgorderr1   r1   r2   r   '   s   
(







r   r)   Tc           
      C  sR  t |d}t|d}t| ddd} |du rd}|dk r"| jd | }| jdkr/| dddf } | dd|f }|d	u r@|d }n+|d
u rJ| jd }n!|dk rW| jd | d }|| jd kri| jd }tdt |}t||dd}t	|}t	|| jd }	|r||v r|
|| n|	
|	| t| |d|f || |d|	f fS )a  
    Returns an array with lags included given an array.

    Parameters
    ----------
    x : array_like
        An array or NumPy ndarray subclass. Can be either a 1d or 2d array with
        observations in columns.
    col : int or None
        `col` can be an int of the zero-based column index. If it's a
        1d array `col` can be None.
    lags : int
        The number of lags desired.
    drop : bool
        Whether to keep the contemporaneous variable for the data.
    insert : bool or int
        If True, inserts the lagged values after `col`. If False, appends
        the data. If int inserts the lags at int.

    Returns
    -------
    array : ndarray
        Array with lags

    Examples
    --------

    >>> import statsmodels.api as sm
    >>> data = sm.datasets.macrodata.load()
    >>> data = data.data[['year','quarter','realgdp','cpi']]
    >>> data = sm.tsa.add_lag(data, 'realgdp', lags=2)

    Notes
    -----
    Trims the array both forward and backward, so that the array returned
    so that the length of the returned array is len(`X`) - lags. The lags are
    returned in increasing order, ie., t-1,t-2,...,t-lags
    lagsdroprP   r*   )rJ   Nr   r)   TFz<insert > number of variables, inserting at the last positionZBoth)trim)r   r   r   rK   rJ   warningswarnr
   r   r   popr?   r-   rO   )
rP   colrU   rV   insertZcontempZins_idxZndlagsZ
first_colsZ	last_colsr1   r1   r2   add_lag   s>   
'



(r]   c                 C  s   t |d}t |d}| jdkrt|dkr| j} n	| jdkr"td| jd }|dkr4| | jdd }ntjt	t
||d d}tj|| }| t|| }| jdkrat|dkra|j}|S )	a  
    Detrend an array with a trend of given order along axis 0 or 1.

    Parameters
    ----------
    x : array_like, 1d or 2d
        Data, if 2d, then each row or column is independently detrended with
        the same trendorder, but independent trend estimates.
    order : int
        The polynomial order of the trend, zero is constant, one is
        linear trend, two is quadratic trend.
    axis : int
        Axis can be either 0, observations by rows, or 1, observations by
        columns.

    Returns
    -------
    ndarray
        The detrended series is the residual of the linear regression of the
        data on the trend of given order.
    rT   r5   r*   r)   z0x.ndim > 2 is not implemented until it is neededr   r4   )N)r   rJ   intTrC   rK   Zmeanr-   rH   rI   floatZlinalgZpinvdot)rP   rT   r5   rR   ZresidZtrendsZbetar1   r1   r2   detrend   s"   



rc   forwardexmaxlagr_   rW   .Literal['forward', 'backward', 'both', 'none']originalLiteral['ex', 'sep', 'in']
use_pandasboolreturnKNDArray | DataFrame | tuple[NDArray, NDArray] | tuple[DataFrame, DataFrame]c                   sj  t |d}t|d}t|dddd}t|ddd	}| }t| d
ddd} t|do)|}|du r0dn|}| }|r@|dv r@tdd}| j\}}	|dv rM|	}||krUtdt	|| |	|d  f}
t
dt|d D ]}| |
|| || | |	||  |	|| d  f< qk|dv rd}n|dv r|}ntd|dv rt|
}n|}|r|} t| trdd | jD }tt|| jd krtdnt| jg}dd |D }t
|D ]}t|d  | fdd|D  qt|
d| | j|d}
|
j|d }|dv r|| }|j|dd}n|
|||df }|d kr*|
||d|f }|d kr3||fS |S )!a,	  
    Create 2d array of lags.

    Parameters
    ----------
    x : array_like
        Data; if 2d, observation in rows and variables in columns.
    maxlag : int
        All lags from zero to maxlag are included.
    trim : {'forward', 'backward', 'both', 'none', None}
        The trimming method to use.

        * 'forward' : trim invalid observations in front.
        * 'backward' : trim invalid initial observations.
        * 'both' : trim invalid observations on both sides.
        * 'none', None : no trimming of observations.
    original : {'ex','sep','in'}
        How the original is treated.

        * 'ex' : drops the original array returning only the lagged values.
        * 'in' : returns the original array and the lagged values as a single
          array.
        * 'sep' : returns a tuple (original array, lagged values). The original
                  array is truncated to have the same number of rows as
                  the returned lagmat.
    use_pandas : bool
        If true, returns a DataFrame when the input is a pandas
        Series or DataFrame.  If false, return numpy ndarrays.

    Returns
    -------
    lagmat : ndarray
        The array with lagged observations.
    y : ndarray, optional
        Only returned if original == 'sep'.

    Notes
    -----
    When using a pandas DataFrame or Series with use_pandas=True, trim can only
    be 'forward' or 'both' since it is not possible to consistently extend
    index values.

    Examples
    --------
    >>> from statsmodels.tsa.tsatools import lagmat
    >>> import numpy as np
    >>> X = np.arange(1,7).reshape(-1,2)
    >>> lagmat(X, maxlag=2, trim="forward", original='in')
    array([[ 1.,  2.,  0.,  0.,  0.,  0.],
       [ 3.,  4.,  1.,  2.,  0.,  0.],
       [ 5.,  6.,  3.,  4.,  1.,  2.]])

    >>> lagmat(X, maxlag=2, trim="backward", original='in')
    array([[ 5.,  6.,  3.,  4.,  1.,  2.],
       [ 0.,  0.,  5.,  6.,  3.,  4.],
       [ 0.,  0.,  0.,  0.,  5.,  6.]])

    >>> lagmat(X, maxlag=2, trim="both", original='in')
    array([[ 5.,  6.,  3.,  4.,  1.,  2.]])

    >>> lagmat(X, maxlag=2, trim="none", original='in')
    array([[ 1.,  2.,  0.,  0.,  0.,  0.],
       [ 3.,  4.,  1.,  2.,  0.,  0.],
       [ 5.,  6.,  3.,  4.,  1.,  2.],
       [ 0.,  0.,  5.,  6.,  3.,  4.],
       [ 0.,  0.,  0.,  0.,  5.,  6.]])
    rf   rj   rW   Trd   backwardbothnoneoptionalr$   rh   )re   sepinr#   rP   r*   N)rJ   r,   rq   )rq   ro   zEtrim cannot be 'none' or 'backward' when used on Series or DataFramesr   )re   rt   zmaxlag should be < nobsr)   )rq   rd   )ro   rp   ztrim option not validc                 S  r6   r1   r7   r9   r1   r1   r2   r;     r<   zlagmat.<locals>.<listcomp>zSColumns names must be distinct after conversion to string (if not already strings).c                 S  r6   r1   r7   r:   r[   r1   r1   r2   r;     r<   c                   s   g | ]
}t |d    qS )z.L.r7   rv   Zlag_strr1   r2   r;     s    r>   )rt   re   r4   rt   )r   r   r   r   r	   lowerrM   rK   r-   zerosranger_   rG   rD   r   r@   setr8   nameextendr?   ilocrV   )rP   rf   rW   rh   rj   ZorigrQ   ZdropidxrR   nvarZlmkZstartobsZstopobsZ	x_columnsr@   ZlagrU   Zleadsr1   rw   r2   r   )  s   
I






r   c              	   C  s  t |d}t |ddd}t|dddd}|du r|}t||}t| d}| jd	kr:|r1t| } n| dddf } n| jd
ksD| jdkrHtd| j\}}	|r|rt	| j
ddd
f ||ddd}
|
j
ddd|d	 f g}td	|	D ]"}t	| j
dd|f ||ddd}
||
j
dd||d	 f  qttj|d	dS |rt| } t	| ddd
f ||ddddd|d	 f g}td	|	D ]}|t	| dd|f ||dddd||d	 f  qt|S )a  
    Generate lagmatrix for 2d array, columns arranged by variables.

    Parameters
    ----------
    x : array_like
        Data, 2d. Observations in rows and variables in columns.
    maxlag0 : int
        The first variable all lags from zero to maxlag are included.
    maxlagex : {None, int}
        The max lag for all other variables all lags from zero to maxlag are
        included.
    dropex : int
        Exclude first dropex lags from other variables. For all variables,
        except the first, lags from dropex to maxlagex are included.
    trim : str
        The trimming method to use.

        * 'forward' : trim invalid observations in front.
        * 'backward' : trim invalid initial observations.
        * 'both' : trim invalid observations on both sides.
        * 'none' : no trimming of observations.
    use_pandas : bool
        If true, returns a DataFrame when the input is a pandas
        Series or DataFrame.  If false, return numpy ndarrays.

    Returns
    -------
    ndarray
        The array with lagged observations, columns ordered by variable.

    Notes
    -----
    Inefficient implementation for unequal lags, implemented for convenience.
    maxlag0maxlagexT)rs   rW   rn   rr   Nr)   r   r*   z'Only supports 1 and 2-dimensional data.ru   )rW   rh   rj   r4   )rW   rh   )r   r   maxr	   rJ   rE   r   rM   rK   r   r~   rz   appendrN   r-   rF   rO   )rP   r   r   ZdropexrW   rj   rf   rQ   rR   r   rU   Zlagslir   r1   r1   r2   r     sR   
&



"
.
r   c                 C  s
   |  dS )NF)ravelZmatr1   r1   r2   r     s   
r   c                 C  s   | j tt| S N)r`   take_triu_indicesrG   r   r1   r1   r2   r     s   r   c                 C     t | \}}||  | S r   )r-   Ztril_indicesr   rowsZcolsr1   r1   r2   _tril_indices#     r   c                 C  r   r   )r-   triu_indicesr   r1   r1   r2   r   (  r   r   c                 C  r   r   )r-   diag_indicesr   r1   r1   r2   _diag_indices-  r   r   c                 C  s8   t tt| }|| t| ksJ | j||fddS )Nr   rT   )r_   r-   sqrtrG   reshape)vr   r1   r1   r2   r   2  s   r   c                 C  sl   ddt ddt|     }tt |}t ||f}| |t |< ||j }|t |  d  < |S )Ng      ?r=   r)      r*   )	r-   r   rG   r_   roundry   r   r`   r   )r   r   resultr1   r1   r2   r   8  s   
r   c                 C  s6   t | d} t| | d  d }tdd |D jS )z
    Create duplication matrix D_n which satisfies vec(S) = D_n vech(S) for
    symmetric matrix S

    Returns
    -------
    D_n : ndarray
    r   r)   r*   c                 S  s   g | ]}t | qS r1   )r   r   )r:   rP   r1   r1   r2   r;   R  s    z&duplication_matrix.<locals>.<listcomp>)r   r-   eyeZarrayr`   )r   tmpr1   r1   r2   r   G  s   
	r   c                 C  s8   t | d} ttt| | f}t| |  |dk S )z
    Create the elimination matrix L_n which satisfies vech(M) = L_n vec(M) for
    any matrix M

    Parameters
    ----------

    Returns
    -------
    r   r   )r   r   r-   ZtrilZonesr   )r   Zvech_indicesr1   r1   r2   r   U  s   
r   c                 C  sP   t | d} t |d}t| | }t| | j| |fdd}|j| ddS )z
    Create the commutation matrix K_{p,q} satisfying vec(A') = K_{p,q} vec(A)

    Parameters
    ----------
    p : int
    q : int

    Returns
    -------
    K : ndarray (pq x pq)
    pqr   r   r   r4   )r   r-   r   rI   r   r   r   )r   r   Kindicesr1   r1   r2   r   e  s
   

r   c              	   C  s~   t | d }t | d }tdt| D ]'}|| }t|D ]}||  |||| d   8  < q|d| |d|< q|S )z
    Transforms params to induce stationarity/invertability.

    Parameters
    ----------
    params : array_like
        The AR coefficients

    Reference
    ---------
    Jones(1980)
    r*   r)   N)r-   Ztanhrz   rG   )params	newparamsr   jakiterr1   r1   r2   _ar_transparamsz  s   "r   c                 C  s   |   } |   }tt| d ddD ]-}| | }t|D ]}| | || || d    d|d   ||< q|d| | d|< qdt|  }|S )z
    Inverse of the Jones reparameterization

    Parameters
    ----------
    params : array_like
        The transformed AR coefficients
    r)   r   r=   r*   N)rA   rz   rG   r-   Zarctanh)r   r   r   r   r   Z
invarcoefsr1   r1   r2   _ar_invtransparams  s   	

r   c              	   C  s   dt |   dt |     }dt |   dt |     }tdt| D ]'}|| }t|D ]}||  |||| d   7  < q5|d| |d|< q+|S )z
    Transforms params to induce stationarity/invertability.

    Parameters
    ----------
    params : ndarray
        The ma coeffecients of an (AR)MA model.

    Reference
    ---------
    Jones(1980)
    r)   N)r-   ZexprA   rz   rG   )r   r   r   r   br   r1   r1   r2   _ma_transparams  s   $$"r   c                 C  s   |   }tt| d ddD ]-}| | }t|D ]}| | || || d    d|d   ||< q|d| | d|< qtd|  d|    }|S )z
    Inverse of the Jones reparameterization

    Parameters
    ----------
    params : ndarray
        The transformed MA coefficients
    r)   r   r=   r*   N)rA   rz   rG   r-   log)Zmacoefsr   r   r   r   Z
invmacoefsr1   r1   r2   _ma_invtransparams  s   	

r   c                   s8   t  d d  t fddt ddD S )a  
    Returns the successive differences needed to unintegrate the series.

    Parameters
    ----------
    x : array_like
        The original series
    d : int
        The number of differences of the differenced series.

    Returns
    -------
    y : array_like
        The increasing differences from 0 to d-1 of the first d elements
        of x.

    See Also
    --------
    unintegrate
    dNc                   s    g | ]}t  | d  qS )r   )r-   Zdiff)r:   ir   rP   r1   r2   r;     s     z&unintegrate_levels.<locals>.<listcomp>r   r=   )r   r-   Zasarrayrz   )rP   r   r1   r   r2   unintegrate_levels  s   
"r   c                 C  s\   t |dd }t|dkr |d}tttj|| f |S |d }ttj|| f S )ay  
    After taking n-differences of a series, return the original series

    Parameters
    ----------
    x : array_like
        The n-th differenced series
    levels : list
        A list of the first-value in each differenced series, for
        [first-difference, second-difference, ..., n-th difference]

    Returns
    -------
    y : array_like
        The original series de-differenced

    Examples
    --------
    >>> x = np.array([1, 3, 9., 19, 8.])
    >>> levels = unintegrate_levels(x, 2)
    >>> levels
    array([ 1.,  2.])
    >>> unintegrate(np.diff(x, 2), levels)
    array([  1.,   3.,   9.,  19.,   8.])
    Nr)   r=   r   )listrG   rZ   unintegrater-   ZcumsumZr_)rP   ZlevelsZx0r1   r1   r2   r     s   
r   freqstr | offsets.DateOffsetc                 C  s   t | tjs
t| } t | tjsJ | j } d}| dv s"| |r$dS | dks-| dr/dS | dks8| dr:d	S | d
ksC| drEdS | dkrKdS | dkrQdS | dkrWdS td| )a$  
    Convert a pandas frequency to a periodicity

    Parameters
    ----------
    freq : str or offset
        Frequency to convert

    Returns
    -------
    int
        Periodicity of freq

    Notes
    -----
    Annual maps to 1, quarterly maps to 4, monthly to 12, weekly to 52.
    )zA-zAS-zY-zYS-zYE-)AYr)   Q)zQ-ZQSZQE   M)zM-ZMSZME   WzW-4   D   B   H   zDfreq {} not understood. Please report if you think this is in error.)	rD   r   Z
DateOffsetr   Z	rule_codeupper
startswithrM   format)r   Zyearly_freqsr1   r1   r2   r     s.   
r   )r   Fr   )Nr)   FT)r)   r   )rd   re   F)
rf   r_   rW   rg   rh   ri   rj   rk   rl   rm   )Nr   rd   F)r   r   rl   r_   )3Z
__future__r   Zstatsmodels.compat.pythonr   rX   Znumpyr-   ZpandasrE   r   Zpandas.tseriesr   Zpandas.tseries.frequenciesr   typingr   Zstatsmodels.tools.datar   r	   rB   r
   Zstatsmodels.tools.typingr   Zstatsmodels.tools.validationr   r   r   r   __all__r   r]   rc   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r1   r1   r1   r2   <module>   sT    
 

P1 
W"