a
    Of9                     @  s   d Z ddlmZ ddlm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 dd
lmZ dZG dd dZG dd deZG dd deZG dd deZG dd deZG dd deZG dd deZG dd deZdS )zLIndexer objects for computing start/end window bounds for rolling operations    )annotations)	timedeltaN)
BaseOffset) calculate_variable_window_bounds)Appender)ensure_platform_int)DatetimeIndex)Nanoa  
Computes the bounds of a window.

Parameters
----------
num_values : int, default 0
    number of values that will be aggregated over
window_size : int, default 0
    the number of rows in a window
min_periods : int, default None
    min_periods passed from the top level rolling API
center : bool, default None
    center passed from the top level rolling API
closed : str, default None
    closed passed from the top level rolling API
step : int, default None
    step passed from the top level rolling API
    .. versionadded:: 1.5
win_type : str, default None
    win_type passed from the top level rolling API

Returns
-------
A tuple of ndarray[int64]s, indicating the boundaries of each
window
c                	   @  sF   e Zd ZdZddddddd	Zeeddd
ddd
ddddZdS )BaseIndexera  
    Base class for window bounds calculations.

    Examples
    --------
    >>> from pandas.api.indexers import BaseIndexer
    >>> class CustomIndexer(BaseIndexer):
    ...     def get_window_bounds(self, num_values, min_periods, center, closed, step):
    ...         start = np.empty(num_values, dtype=np.int64)
    ...         end = np.empty(num_values, dtype=np.int64)
    ...         for i in range(num_values):
    ...             start[i] = i
    ...             end[i] = i + self.window_size
    ...         return start, end
    >>> df = pd.DataFrame({"values": range(5)})
    >>> indexer = CustomIndexer(window_size=2)
    >>> df.rolling(indexer).sum()
        values
    0	1.0
    1	3.0
    2	5.0
    3	7.0
    4	4.0
    Nr   np.ndarray | NoneintNone)index_arraywindow_sizereturnc                 K  s.   || _ || _| D ]\}}t| || qd S N)r   r   itemssetattr)selfr   r   kwargskeyvalue r   U/var/www/ai-form-bot/venv/lib/python3.9/site-packages/pandas/core/indexers/objects.py__init__H   s    zBaseIndexer.__init__
int | Nonebool | None
str | Nonetuple[np.ndarray, np.ndarray]
num_valuesmin_periodscenterclosedstepr   c                 C  s   t d S r   )NotImplementedErrorr   r    r!   r"   r#   r$   r   r   r   get_window_boundsQ   s    	zBaseIndexer.get_window_bounds)Nr   )r   NNNN)__name__
__module____qualname____doc__r   r   get_window_bounds_docr'   r   r   r   r   r
   .   s    	     r
   c                	   @  s2   e Zd ZdZeedddddddd	d
dZdS )FixedWindowIndexerz3Creates window boundaries that are of fixed length.r   Nr   r   r   r   r   r   c           	      C  s   |s| j dkr| j d d }nd}tjd| |d | |dd}|| j  }|dv rZ|d8 }|dv rj|d8 }t|d|}t|d|}||fS )Nr         int64Zdtypeleftboth)r3   Zneither)r   nparangeclip)	r   r    r!   r"   r#   r$   offsetendstartr   r   r   r'   `   s    	
z$FixedWindowIndexer.get_window_bounds)r   NNNNr(   r)   r*   r+   r   r,   r'   r   r   r   r   r-   ]   s        r-   c                	   @  s2   e Zd ZdZeedddddddd	d
dZdS )VariableWindowIndexerzNCreates window boundaries that are of variable length, namely for time series.r   Nr   r   r   r   r   r   c                 C  s   t || j|||| jS r   )r   r   r   r&   r   r   r   r'   ~   s    z'VariableWindowIndexer.get_window_bounds)r   NNNNr;   r   r   r   r   r<   {   s        r<   c                	      sR   e Zd ZdZddddddd	 fd
dZeeddddddddddZ  ZS )VariableOffsetWindowIndexeraP  
    Calculate window boundaries based on a non-fixed offset such as a BusinessDay.

    Examples
    --------
    >>> from pandas.api.indexers import VariableOffsetWindowIndexer
    >>> df = pd.DataFrame(range(10), index=pd.date_range("2020", periods=10))
    >>> offset = pd.offsets.BDay(1)
    >>> indexer = VariableOffsetWindowIndexer(index=df.index, offset=offset)
    >>> df
                0
    2020-01-01  0
    2020-01-02  1
    2020-01-03  2
    2020-01-04  3
    2020-01-05  4
    2020-01-06  5
    2020-01-07  6
    2020-01-08  7
    2020-01-09  8
    2020-01-10  9
    >>> df.rolling(indexer).sum()
                   0
    2020-01-01   0.0
    2020-01-02   1.0
    2020-01-03   2.0
    2020-01-04   3.0
    2020-01-05   7.0
    2020-01-06  12.0
    2020-01-07   6.0
    2020-01-08   7.0
    2020-01-09   8.0
    2020-01-10   9.0
    Nr   r   r   zDatetimeIndex | NonezBaseOffset | Noner   )r   r   indexr8   r   c                   sJ   t  j||fi | t|ts(td|| _t|ts@td|| _d S )Nzindex must be a DatetimeIndex.z(offset must be a DateOffset-like object.)superr   
isinstancer   
ValueErrorr>   r   r8   )r   r   r   r>   r8   r   	__class__r   r   r      s    

z$VariableOffsetWindowIndexer.__init__r   r   r   r   r   c                 C  s  |d urt d|dkr4tjdddtjdddfS |d u rN| jd urJdnd}|dv }|dv }| j|d	  | jd k r|d
}nd	}|| j }	tj|dd}
|
d
 tj|dd}|d
 d|
d< |rd	|d< nd|d< td}td	|D ]}| j| }||	 }|r|td	8 }||
|< t|
|d	  |D ]0}| j| | | }||kr,||
|<  q^q,| j||d	   | | }||kr|s||d	  d	 ||< n(||kr|d	 ||< n||d	  ||< |s||  d	8  < q|
|fS )Nz/step not implemented for variable offset windowr   r0   r1   rightr4   )rD   r4   r2   r.   )	r%   r5   emptyr>   r8   fillr   ranger	   )r   r    r!   r"   r#   r$   Zright_closedZleft_closedZindex_growth_signZoffset_diffr:   r9   zeroiZ	end_boundZstart_boundjZ
start_diffZend_diffr   r   r   r'      sR    	







z-VariableOffsetWindowIndexer.get_window_bounds)Nr   NN)r   NNNN)	r(   r)   r*   r+   r   r   r,   r'   __classcell__r   r   rB   r   r=      s   %         r=   c                	   @  s2   e Zd ZdZeedddddddd	d
dZdS )ExpandingIndexerz;Calculate expanding window bounds, mimicking df.expanding()r   Nr   r   r   r   r   r   c                 C  s&   t j|t jdt jd|d t jdfS )Nr1   r.   )r5   Zzerosr0   r6   r&   r   r   r   r'     s    
z"ExpandingIndexer.get_window_bounds)r   NNNNr;   r   r   r   r   rM     s        rM   c                	   @  s2   e Zd ZdZeedddddddd	d
dZdS )FixedForwardWindowIndexera  
    Creates window boundaries for fixed-length windows that include the current row.

    Examples
    --------
    >>> df = pd.DataFrame({'B': [0, 1, 2, np.nan, 4]})
    >>> df
         B
    0  0.0
    1  1.0
    2  2.0
    3  NaN
    4  4.0

    >>> indexer = pd.api.indexers.FixedForwardWindowIndexer(window_size=2)
    >>> df.rolling(window=indexer, min_periods=1).sum()
         B
    0  1.0
    1  3.0
    2  2.0
    3  4.0
    4  4.0
    r   Nr   r   r   r   r   r   c                 C  s`   |rt d|d urt d|d u r(d}tjd||dd}|| j }| jrXt|d|}||fS )Nz.Forward-looking windows can't have center=TruezAForward-looking windows don't support setting the closed argumentr.   r   r0   r1   )rA   r5   r6   r   r7   )r   r    r!   r"   r#   r$   r:   r9   r   r   r   r'   B  s    	
z+FixedForwardWindowIndexer.get_window_bounds)r   NNNNr;   r   r   r   r   rN   )  s        rN   c                	      s^   e Zd ZdZdddedfddddddd	 fd
dZeeddddddddddZ  Z	S )GroupbyIndexerzMCalculate bounds to compute groupby rolling, mimicking df.groupby().rolling()Nr   r   zint | BaseIndexerzdict | Noneztype[BaseIndexer]r   )r   r   groupby_indiceswindow_indexerindexer_kwargsr   c                   sH   |pi | _ || _|r| ni | _t jf || jd|d| dS )a4  
        Parameters
        ----------
        index_array : np.ndarray or None
            np.ndarray of the index of the original object that we are performing
            a chained groupby operation over. This index has been pre-sorted relative to
            the groups
        window_size : int or BaseIndexer
            window size during the windowing operation
        groupby_indices : dict or None
            dict of {group label: [positional index of rows belonging to the group]}
        window_indexer : BaseIndexer
            BaseIndexer class determining the start and end bounds of each group
        indexer_kwargs : dict or None
            Custom kwargs to be passed to window_indexer
        **kwargs :
            keyword arguments that will be available when get_window_bounds is called
        r   r   r   N)rP   rQ   copyrR   r?   r   pop)r   r   r   rP   rQ   rR   r   rB   r   r   r   _  s    
zGroupbyIndexer.__init__r   r   r   r   r   r   c                 C  sZ  g }g }d}| j  D ]\}	}
| jd ur:| jt|
}n| j}| jf || jd| j}|t	|
||||\}}|
tj}|
tj}t	|t	|ksJ dt||t	|
 }|t	|
7 }t||d d gj
tjdd}||t| ||t| qt	|dkr>tjg tjdtjg tjdfS t|}t|}||fS )	Nr   rS   z6these should be equal in length from get_window_boundsrE   r.   F)rT   r1   )rP   r   r   Ztaker   rQ   r   rR   r'   lenZastyper5   r0   r6   appendarrayZconcatenate)r   r    r!   r"   r#   r$   Zstart_arraysZ
end_arraysZwindow_indices_startr   indicesr   Zindexerr:   r9   Zwindow_indicesr   r   r   r'     sJ    
 

z GroupbyIndexer.get_window_bounds)r   NNNN)
r(   r)   r*   r+   r
   r   r   r,   r'   rL   r   r   rB   r   rO   \  s   $     rO   c                	   @  s2   e Zd ZdZeedddddddd	d
dZdS )ExponentialMovingWindowIndexerz/Calculate ewm window bounds (the entire window)r   Nr   r   r   r   r   r   c                 C  s$   t jdgt jdt j|gt jdfS )Nr   r1   )r5   rX   r0   r&   r   r   r   r'     s    	z0ExponentialMovingWindowIndexer.get_window_bounds)r   NNNNr;   r   r   r   r   rZ     s        rZ   )r+   
__future__r   datetimer   numpyr5   Zpandas._libs.tslibsr   Zpandas._libs.window.indexersr   Zpandas.util._decoratorsr   Zpandas.core.dtypes.commonr   Zpandas.core.indexes.datetimesr   Zpandas.tseries.offsetsr	   r,   r
   r-   r<   r=   rM   rN   rO   rZ   r   r   r   r   <module>   s&   / 3]