o
    0GfV,                     @   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 ddlmZ g d	Zd
d Zdd Z					dddZG dd dZdS )z+
Seasonal Decomposition by Moving Averages
    N)nanmean)PandasWrapper
array_like)STL)convolution_filter)MSTL)freq_to_period)r   seasonal_decomposeseasonal_meanDecomposeResultr   c           	      C   sn  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ri| }|| 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   (    | ]\}}t t |s|V  qd S NnpanyZisnan.0iZvals r   8lib/python3.10/site-packages/statsmodels/tsa/seasonal.py	<genexpr>   s    
z%_extrapolate_trend.<locals>.<genexpr>r      c                 s   r   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>H   s   " z!seasonal_mean.<locals>.<listcomp>)r   arrayrange)r)   r(   r   r'   r   r
   B   s   r
   additiveTc                 C   sF  |}t | }|du rtt| dddd}t| ddd} t| }tt| s+td|dr;t	| d	kr;td
|du rN|durJt
|}|}ntd| jd	 d| k rgtdd|  d| jd	  d|du r|d d	krtdgdg|d   dg | }ntd| |}t|d }	t| ||	}
|dkr|d }|d	krt|
|d }
|dr| |
 }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 (e.g., 1 for annual, 4 for quarterly, etc). 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   )r1   r!   r2   observed)r   getattrr   lenr   allZisfinite
ValueError
startswithr   r   r   r+   repeatintr   r$   r
   ZmeanZtiler   zipappendwrapr    r   )r)   ZmodelZfiltr(   Z	two_sidedZextrapolate_trendZpfreqZpwnobsZnsidesr!   Z	detrendedZperiod_averagesr1   r2   resultssnamer   r   r   r	   K   st   F
&



 
r	   c                   @   sv   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.   rC   )	_seasonal_trendr   Z	ones_like
isinstancepdSeriesr.   _weights_resid	_observed)selfr5   r1   r!   r2   rD   r   r   r   __init__   s   

zDecomposeResult.__init__c                 C      | j S )zObserved data)rL   rM   r   r   r   r5         zDecomposeResult.observedc                 C   rO   )z The estimated seasonal component)rE   rP   r   r   r   r1     rQ   zDecomposeResult.seasonalc                 C   rO   )zThe estimated trend component)rF   rP   r   r   r   r!   	  rQ   zDecomposeResult.trendc                 C   rO   )zThe estimated residuals)rK   rP   r   r   r   r2     rQ   zDecomposeResult.residc                 C   rO   )z)The weights used in the robust estimation)rJ   rP   r   r   r   rD     rQ   zDecomposeResult.weightsc                 C   s   | j jS )zNumber of observations)rL   r   rP   r   r   r   r@     s   zDecomposeResult.nobsTFc                 C   s>  ddl m} ddlm} | }|  |r| jdfgng }	|	|r%| jdfgng 7 }	| jjdkr;|	|r7| jdfgng 7 }	n@| jjdkr{t| jt	j
r^| jjD ]}
|	|rY| j|
 dfgng 7 }	qLnt| jjd D ]}|	|rw| jdd|f dfgng 7 }	qf|	|r| 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}|jt|	ddd\}}tt||	D ]I\}\}\}	}|d	kr||	 n|j|	ddd |j|dddd t|	d|}|dkr| }|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!   r   r1   NZresidualrD   T)ZsharexoZnone)ZmarkerZ	linestyle)r   r   z#000000)ZcolorZzorderrC   )Zpandas.plottingrR   Zstatsmodels.graphics.utilsrS   rL   r!   r1   r   rG   rH   Z	DataFramer3   r,   r   r2   rD   rI   r.   Zsubplotsr7   r   r=   plotr6   
capitalizeZ	set_titleZ
set_ylabelZset_xlimZtight_layout)rM   r5   r1   r!   r2   rD   rR   rS   ZpltZseriescolr   r@   ZxlimZfigZaxsZaxZdef_namerC   titler   r   r   rV     sN   
zDecomposeResult.plotr   )TTTTF)__name__
__module____qualname____doc__rN   propertyr5   r1   r!   r2   rD   r@   rV   r   r   r   r   r      s*    






r   )r-   NNTr   )r]   Znumpyr   ZpandasrH   Zpandas.core.nanopsr   r&   Zstatsmodels.tools.validationr   r   Zstatsmodels.tsa.stl._stlr   Z#statsmodels.tsa.filters.filtertoolsr   Zstatsmodels.tsa.stl.mstlr   Zstatsmodels.tsa.tsatoolsr   __all__r$   r
   r	   r   r   r   r   r   <module>   s(    	+
 