o
    ôT·j‘9  ã                   @  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                   @  s<   e Zd ZdZ	ddd
d„Zeeƒ					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   Úindex_arrayúnp.ndarray | NoneÚwindow_sizeÚintÚreturnÚNonec                 K  s.   || _ || _| ¡ D ]
\}}t| ||ƒ q
d S ©N)r   r   ÚitemsÚsetattr)Úselfr   r   ÚkwargsÚkeyÚvalue© r   ú_/home/dinkstrade/pdmp-scanner/venv/lib/python3.10/site-packages/pandas/core/indexers/objects.pyÚ__init__H   s
   ÿzBaseIndexer.__init__Ú
num_valuesÚmin_periodsú
int | NoneÚcenterúbool | NoneÚclosedú
str | NoneÚstepútuple[np.ndarray, np.ndarray]c                 C  s   t ‚r   )ÚNotImplementedError©r   r   r   r   r    r"   r   r   r   Úget_window_boundsQ   s   	zBaseIndexer.get_window_bounds)Nr   )r   r   r   r   r   r   ©r   NNNN©r   r   r   r   r   r   r    r!   r"   r   r   r#   )Ú__name__Ú
__module__Ú__qualname__Ú__doc__r   r   Úget_window_bounds_docr&   r   r   r   r   r
   .   s    ÿ	úr
   c                   @  ó.   e Zd ZdZeeƒ					dddd„ƒZdS )ÚFixedWindowIndexerz3Creates window boundaries that are of fixed length.r   Nr   r   r   r   r   r   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 r-|d8 }|dv r5|d8 }t |d|¡}t |d|¡}||fS )Nr   é   é   Úint64©Údtype©ÚleftÚboth)r6   Úneither)r   ÚnpÚarangeÚclip)	r   r   r   r   r    r"   ÚoffsetÚendÚstartr   r   r   r&   `   s   	
z$FixedWindowIndexer.get_window_boundsr'   r(   ©r)   r*   r+   r,   r   r-   r&   r   r   r   r   r/   ]   ó    úr/   c                   @  r.   )ÚVariableWindowIndexerzNCreates window boundaries that are of variable length, namely for time series.r   Nr   r   r   r   r   r   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_boundsr'   r(   r?   r   r   r   r   rA   {   r@   rA   c                      sJ   e Zd ZdZ				dd‡ fdd„Zeeƒ					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   r   r   ÚindexúDatetimeIndex | Noner<   úBaseOffset | Noner   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   Ú
ValueErrorrC   r   r<   )r   r   r   rC   r<   r   ©Ú	__class__r   r   r   ¹   s   


z$VariableOffsetWindowIndexer.__init__r   r   r   r   r   r    r!   r"   r#   c                 C  sÖ  |d urt dƒ‚|dkrtjddd�tjddd�fS |d u r'| jd ur%d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< |rhd	|d< nd|d< tdƒ}td	|ƒD ]q}| j| }||	 }|rˆ|td	ƒ8 }||
|< t|
|d	  |ƒD ]}| j| | | }||krª||
|<  nq•| j||d	   | | }||krÉ|sÉ||d	  d	 ||< n||krÔ|d	 ||< n||d	  ||< |sæ||  d	8  < qu|
|fS )Nz/step not implemented for variable offset windowr   r2   r3   Úrightr7   )rK   r7   r5   r0   éÿÿÿÿ)	r$   r9   ÚemptyrC   r<   Úfillr   Úranger	   )r   r   r   r   r    r"   Úright_closedÚleft_closedÚindex_growth_signÚoffset_diffr>   r=   ÚzeroÚiÚ	end_boundÚstart_boundÚjÚ
start_diffÚend_diffr   r   r   r&   É   sV   	




þ€z-VariableOffsetWindowIndexer.get_window_bounds)Nr   NN)
r   r   r   r   rC   rD   r<   rE   r   r   r'   r(   )	r)   r*   r+   r,   r   r   r-   r&   Ú__classcell__r   r   rI   r   rB   •   s    %ûúrB   c                   @  r.   )ÚExpandingIndexerz;Calculate expanding window bounds, mimicking df.expanding()r   Nr   r   r   r   r   r   r    r!   r"   r   r#   c                 C  s&   t j|t jd�t jd|d t jd�fS )Nr3   r0   )r9   Úzerosr2   r:   r%   r   r   r   r&     s   
þz"ExpandingIndexer.get_window_boundsr'   r(   r?   r   r   r   r   r\     r@   r\   c                   @  r.   )Ú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   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r,t |d|¡}||fS )Nz.Forward-looking windows can't have center=TruezAForward-looking windows don't support setting the closed argumentr0   r   r2   r3   )rH   r9   r:   r   r;   )r   r   r   r   r    r"   r>   r=   r   r   r   r&   B  s   	ÿ
z+FixedForwardWindowIndexer.get_window_boundsr'   r(   r?   r   r   r   r   r^   )  s    úr^   c                      sL   e Zd ZdZdddedfd‡ fdd„Zeeƒ					dddd„ƒZ‡  Z	S ) ÚGroupbyIndexerzMCalculate bounds to compute groupby rolling, mimicking df.groupby().rolling()Nr   r   r   r   úint | BaseIndexerÚgroupby_indicesúdict | NoneÚwindow_indexerútype[BaseIndexer]Úindexer_kwargsr   r   c                   sH   |pi | _ || _|r| ¡ ni | _tƒ jd|| 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   Nr   )ra   rc   Úcopyre   rF   r   Úpop)r   r   r   ra   rc   re   r   rI   r   r   r   _  s   
þ
ýzGroupbyIndexer.__init__r   r   r   r   r   r   r    r!   r"   r#   c                 C  sX  g }g }d}| j  ¡ D ]|\}	}
| jd ur| j t|
ƒ¡}n| j}| jd	|| jdœ| j¤Ž}| t	|
ƒ||||¡\}}| 
tj¡}| 
tj¡}t	|ƒt	|ƒksRJ 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   rf   z6these should be equal in length from get_window_boundsrL   r0   F)rg   r3   r   )ra   r   r   Útaker   rc   r   re   r&   ÚlenÚastyper9   r2   r:   ÚappendÚarrayÚconcatenate)r   r   r   r   r    r"   Ústart_arraysÚ
end_arraysÚwindow_indices_startr   Úindicesr   Úindexerr>   r=   Úwindow_indicesr   r   r   r&   ƒ  sJ   
þýÿÿþÿÿ 

z GroupbyIndexer.get_window_bounds)r   r   r   r`   ra   rb   rc   rd   re   rb   r   r   r'   r(   )
r)   r*   r+   r,   r
   r   r   r-   r&   r[   r   r   rI   r   r_   \  s    ú$úr_   c                   @  r.   )ÚExponentialMovingWindowIndexerz/Calculate ewm window bounds (the entire window)r   Nr   r   r   r   r   r   r    r!   r"   r   r#   c                 C  s$   t jdgt jd�t j|gt jd�fS )Nr   r3   )r9   rm   r2   r%   r   r   r   r&   ¼  s   $	z0ExponentialMovingWindowIndexer.get_window_boundsr'   r(   r?   r   r   r   r   ru   ¹  r@   ru   )r,   Ú
__future__r   Údatetimer   Únumpyr9   Úpandas._libs.tslibsr   Úpandas._libs.window.indexersr   Úpandas.util._decoratorsr   Úpandas.core.dtypes.commonr   Úpandas.core.indexes.datetimesr   Úpandas.tseries.offsetsr	   r-   r
   r/   rA   rB   r\   r^   r_   ru   r   r   r   r   Ú<module>   s(    / 3]