U
    c$2                     @  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	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) calculate_variable_window_bounds)Appender)ensure_platform_int)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 )BaseIndexerz*Base class for window bounds calculations.Nr   np.ndarray | NoneintNoneindex_arraywindow_sizereturnc                 K  s.   || _ || _| D ]\}}t| || qdS )z
        Parameters
        ----------
        **kwargs :
            keyword arguments that will be available when get_window_bounds is called
        N)r   r   itemssetattr)selfr   r   kwargskeyvalue r   @/tmp/pip-unpacked-wheel-g7fro6k3/pandas/core/indexers/objects.py__init__.   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 N)NotImplementedErrorr   r   r   r    r!   r"   r   r   r   get_window_bounds=   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   |r| j d d }nd}tjd| |d | |dd}|| j  }|dkrP|d8 }|dkr`|d8 }t|d|}t|d|}||fS )N      r   int64Zdtypeleftboth)r2   Zneither)r   nparangeclip)	r   r   r   r    r!   r"   offsetendstartr   r   r   r&   M   s    

z$FixedWindowIndexer.get_window_bounds)r   NNNNr'   r(   r)   r*   r   r+   r&   r   r   r   r   r,   J   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&   l   s    z'VariableWindowIndexer.get_window_bounds)r   NNNNr:   r   r   r   r   r;   i   s        r;   c                	      sN   e Zd ZdZddddd fdd	Zeeddd
ddd
ddddZ  ZS )VariableOffsetWindowIndexerzNCalculate window boundaries based on a non-fixed offset such as a BusinessDay.Nr   r	   r
   r   r   c                   s"   t  j||f| || _|| _d S r#   )superr   indexr7   )r   r   r   r>   r7   r   	__class__r   r   r      s    z$VariableOffsetWindowIndexer.__init__r   r   r   r   r   c                 C  s  |d k	rt d|dkr4tjdddtjdddfS |d krN| jd k	rJdnd}|dk}|dk}| j|d	  | jd k r|d
}nd	}tj|dd}	|	d
 tj|dd}
|
d
 d|	d< |rd	|
d< nd|
d< td	|D ]}| j| }| j| || j  }|r|td	8 }||	|< t|	|d	  |D ]0}| j| | | tdkr&||	|<  qXq&| j|
|d	   | | tdkr|d	 |
|< n|
|d	  |
|< |s|
|  d	8  < q|	|
fS )Nz/step not implemented for variable offset windowr   r/   r0   rightr3   )rA   r3   r1   r-   )	r$   r4   emptyr>   fillranger7   r   r   )r   r   r   r    r!   r"   Zright_closedZleft_closedZindex_growth_signr9   r8   iZ	end_boundZstart_boundjr   r   r   r&      sF    





$z-VariableOffsetWindowIndexer.get_window_bounds)Nr   NN)r   NNNN)	r'   r(   r)   r*   r   r   r+   r&   __classcell__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 )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 )Nr0   r-   )r4   zerosr/   r5   r%   r   r   r   r&      s    z"ExpandingIndexer.get_window_bounds)r   NNNNr:   r   r   r   r   rI      s        rI   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 k	rt d|d k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   r/   r0   )
ValueErrorr4   r5   r   r6   )r   r   r   r    r!   r"   r9   r8   r   r   r   r&     s    

z+FixedForwardWindowIndexer.get_window_bounds)r   NNNNr:   r   r   r   r   rK      s        rK   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)rN   rO   copyrP   r=   r   pop)r   r   r   rN   rO   rP   r   r?   r   r   r   &  s    
zGroupbyIndexer.__init__r
   r   r   r   r   r   c                 C  sZ  g }g }d}| j  D ]\}	}
| jd k	r:| jt|
}n| j}| jf || jd| j}|t	|
||||\}}|
tj}|
tj}t	|t	|kst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   rQ   z6these should be equal in length from get_window_boundsrB   r-   F)rR   r0   )rN   r   r   Ztaker   rO   r   rP   r&   lenZastyper4   r/   AssertionErrorr5   appendarrayZconcatenate)r   r   r   r    r!   r"   Zstart_arraysZ
end_arraysZwindow_indices_startr   indicesr   Zindexerr9   r8   Zwindow_indicesr   r   r   r&   J  sV    
     
  

z GroupbyIndexer.get_window_bounds)r   NNNN)
r'   r(   r)   r*   r   r   r   r+   r&   rH   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 )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   r0   )r4   rW   r/   r%   r   r   r   r&     s    
z0ExponentialMovingWindowIndexer.get_window_bounds)r   NNNNr:   r   r   r   r   rY     s        rY   )r*   
__future__r   datetimer   Znumpyr4   Zpandas._libs.window.indexersr   Zpandas.util._decoratorsr   Zpandas.core.dtypes.commonr   Zpandas.tseries.offsetsr   r+   r   r,   r;   r<   rI   rK   rM   rY   r   r   r   r   <module>   s    X4^