a
    \:b)                     @   s   d Z ddlZddl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 g dZd	d
 Zdd ZdddZG dd deZdS )z+
Seasonal Decomposition by Moving Averages
    N)nanmean)PandasWrapper
array_like)STL)convolution_filter)freq_to_period)r   seasonal_decomposeseasonal_meanDecomposeResultc           	      C   sp  t dd t| D }| jd d t dd t| ddd D  }t|| |}t||| }tjjtjt	||t
|| f | || ddd \}}t	d|tj|  tj|  j}| jdkr| }|| d|< tjjtjt	||t
|| f | || ddd \}}t	|d | jd tj|  tj|  j}| jdkr\| }|| |d d< | S )	z
    Replace nan values on trend's end-points with least-squares extrapolated
    values with regression considering npoints closest defined points.
    c                 s   s&   | ]\}}t t |s|V  qd S NnpanyZisnan.0iZvals r   7lib/python3.9/site-packages/statsmodels/tsa/seasonal.py	<genexpr>   s   z%_extrapolate_trend.<locals>.<genexpr>r      c                 s   s&   | ]\}}t t |s|V  qd S r   r   r   r   r   r   r      s   N)Zrcond)next	enumerateshapeminmaxr   ZlinalgZlstsqZc_ZarangeZonesTndimsqueeze)	trendZnpointsZfrontZbackZ
front_lastZ
back_firstknZextrar   r   r   _extrapolate_trend   sH    	
"

,r"   c                    s   t  fddt D S )z
    Return means for each period in x. period is an int that gives the
    number of periods per cycle. E.g., 12 for monthly. NaNs are ignored
    in the mean.
    c                    s"   g | ]}t |d   ddqS )Nr   Zaxis)
pd_nanmean)r   r   periodxr   r   
<listcomp>A       z!seasonal_mean.<locals>.<listcomp>)r   arrayrange)r'   r&   r   r%   r   r	   ;   s    r	   additiveTc                 C   sT  |}t | }|du r(tt| dddd}t| ddd} t| }tt| sVtd|drvt	| d	krvtd
|du r|durt
|}|}ntd| jd	 d| k rtdd|  d| jd	  d|du r|d d	krtdgdg|d   dg | }ntd| |}t|d }	t| ||	}
|dkrF|d }|d	kr^t|
|d }
|drt| |
 }n| |
 }t||}|dr|tj|d	d }n|tj|d	d8 }t|j|| d jd| }|dr| | |
 }n|| }g }t||
|| fdD ]"\}}||j| |d qt|d	 |d |d |d dS )a	  
    Seasonal decomposition using moving averages.

    Parameters
    ----------
    x : array_like
        Time series. If 2d, individual series are in columns. x must contain 2
        complete cycles.
    model : {"additive", "multiplicative"}, optional
        Type of seasonal component. Abbreviations are accepted.
    filt : array_like, optional
        The filter coefficients for filtering out the seasonal component.
        The concrete moving average method used in filtering is determined by
        two_sided.
    period : int, optional
        Period of the series. Must be used if x is not a pandas object or if
        the index of x does not have  a frequency. Overrides default
        periodicity of x if x is a pandas object with a timeseries index.
    two_sided : bool, optional
        The moving average method used in filtering.
        If True (default), a centered moving average is computed using the
        filt. If False, the filter coefficients are for past values only.
    extrapolate_trend : int or 'freq', optional
        If set to > 0, the trend resulting from the convolution is
        linear least-squares extrapolated on both ends (or the single one
        if two_sided is False) considering this many (+1) closest points.
        If set to 'freq', use `freq` closest points. Setting this parameter
        results in no NaN values in trend or resid components.

    Returns
    -------
    DecomposeResult
        A object with seasonal, trend, and resid attributes.

    See Also
    --------
    statsmodels.tsa.filters.bk_filter.bkfilter
        Baxter-King filter.
    statsmodels.tsa.filters.cf_filter.cffilter
        Christiano-Fitzgerald asymmetric, random walk filter.
    statsmodels.tsa.filters.hp_filter.hpfilter
        Hodrick-Prescott filter.
    statsmodels.tsa.filters.convolution_filter
        Linear filtering via convolution.
    statsmodels.tsa.seasonal.STL
        Season-Trend decomposition using LOESS.

    Notes
    -----
    This is a naive decomposition. More sophisticated methods should
    be preferred.

    The additive model is Y[t] = T[t] + S[t] + e[t]

    The multiplicative model is Y[t] = T[t] * S[t] * e[t]

    The results are obtained by first estimating the trend by applying
    a convolution filter to the data. The trend is then removed from the
    series and the average of this de-trended series for each period is
    the returned seasonal component.
    NindexZinferred_freqr'      )Zmaxdimz,This function does not handle missing valuesmr   zJMultiplicative seasonality is not appropriate for zero and negative valueszxYou must specify a period or x must be a pandas object with a PeriodIndex or a DatetimeIndex with a freq not set to Nonez'x must have 2 complete cycles requires z observations. x only has z observation(s)g      ?r   g      ?Zfreqr#   )seasonalr   residN)columns   )r0   r   r1   observed)r   getattrr   lenr   allZisfinite
ValueError
startswithr   r   r   r*   repeatintr   r"   r	   ZmeanZtiler   zipappendZwrapr   r
   )r'   ZmodelZfiltr&   Z	two_sidedZextrapolate_trendZpfreqZpwnobsZnsidesr   Z	detrendedZperiod_averagesr0   r1   Zresultssnamer   r   r   r   D   st    E

&



 r   c                   @   sl   e Zd ZdZdddZedd Zedd Zed	d
 Zedd Z	edd Z
edd ZdddZdS )r
   a  
    Results class for seasonal decompositions

    Parameters
    ----------
    observed : array_like
        The data series that has been decomposed.
    seasonal : array_like
        The seasonal component of the data series.
    trend : array_like
        The trend component of the data series.
    resid : array_like
        The residual component of the data series.
    weights : array_like, optional
        The weights used to reduce outlier influence.
    Nc                 C   sR   || _ || _|d u r<t|}t|tjr<tj||jdd}|| _|| _	|| _
d S )Nweights)r-   r@   )	_seasonal_trendr   Z	ones_like
isinstancepdSeriesr-   _weights_resid	_observed)selfr4   r0   r   r1   rA   r   r   r   __init__   s    
zDecomposeResult.__init__c                 C   s   | j S )zObserved data)rI   rJ   r   r   r   r4      s    zDecomposeResult.observedc                 C   s   | j S )z The estimated seasonal component)rB   rL   r   r   r   r0      s    zDecomposeResult.seasonalc                 C   s   | j S )zThe estimated trend component)rC   rL   r   r   r   r     s    zDecomposeResult.trendc                 C   s   | j S )zThe estimated residuals)rH   rL   r   r   r   r1     s    zDecomposeResult.residc                 C   s   | j S )z)The weights used in the robust estimation)rG   rL   r   r   r   rA     s    zDecomposeResult.weightsc                 C   s   | j jS )zNumber of observations)rI   r   rL   r   r   r   r>     s    zDecomposeResult.nobsTFc                 C   s  ddl m} ddlm} | }|  |r4| jdfgng }	|	|rJ| jdfgng 7 }	|	|rb| jdfgng 7 }	|	|rz| jdfgng 7 }	|	|r| jdfgng 7 }	t	| jt
jt
jfr| jjd }
| jjd | jj|
d	  f}nd| jjd d	 f}|t|	d	\}}tt||	D ]\}\}\}	}|dkr2||	 n"|j|	d
dd |j|dddd t|	d|}|dkrr| }|dkr|r|jn|j}|| || q|  |S )a@  
        Plot estimated components

        Parameters
        ----------
        observed : bool
            Include the observed series in the plot
        seasonal : bool
            Include the seasonal component in the plot
        trend : bool
            Include the trend component in the plot
        resid : bool
            Include the residual in the plot
        weights : bool
            Include the weights in the plot (if any)

        Returns
        -------
        matplotlib.figure.Figure
            The figure instance that containing the plot.
        r   )register_matplotlib_converters)_import_mplZObservedr   r0   ZresidualrA   r   oZnone)ZmarkerZ	linestyle)r   r   z#000000)ZcolorZzorderr@   )Zpandas.plottingrM   Zstatsmodels.graphics.utilsrN   rI   r   r0   r1   rA   rD   rE   Z	DataFramerF   r   r-   Zsubplotsr6   r   r<   plotr5   
capitalizeZ	set_titleZ
set_ylabelZset_xlimZtight_layout)rJ   r4   r0   r   r1   rA   rM   rN   ZpltZseriesr>   ZxlimZfigZaxsr   ZaxZdef_namer@   titler   r   r   rQ     s6    

zDecomposeResult.plot)N)TTTTF)__name__
__module____qualname____doc__rK   propertyr4   r0   r   r1   rA   r>   rQ   r   r   r   r   r
      s(   






     r
   )r,   NNTr   )rW   Znumpyr   ZpandasrE   Zpandas.core.nanopsr   r$   Zstatsmodels.tools.validationr   r   Zstatsmodels.tsa._stlr   Z#statsmodels.tsa.filters.filtertoolsr   Zstatsmodels.tsa.tsatoolsr   __all__r"   r	   r   objectr
   r   r   r   r   <module>   s$   +     
 