
    Eg9                    T   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          Z G d de          Z G d de          Z G d de          Z G d de          Z G d de          Z G d de          Z G 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                  T    e Zd ZdZ	 ddd
Z ee          	 	 	 	 	 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                x    || _         || _        |                                D ]\  }}t          | ||           d S N)r   r   itemssetattr)selfr   r   kwargskeyvalues         Q/var/www/sysmax/venv/lib/python3.11/site-packages/pandas/core/indexers/objects.py__init__zBaseIndexer.__init__H   sN     '& ,,.. 	& 	&JCD#u%%%%	& 	&    
num_valuesmin_periods
int | Nonecenterbool | Noneclosed
str | Nonesteptuple[np.ndarray, np.ndarray]c                    t           r   )NotImplementedErrorr   r   r   r!   r#   r%   s         r   get_window_boundszBaseIndexer.get_window_boundsQ   s
     "!r   )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   .   s         4 IJ& & & & & X#$$ "&"!" " " " %$" " "r   r   c                  H    e Zd ZdZ ee          	 	 	 	 	 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                   |s| j         dk    r| j         dz
  dz  }nd}t          j        d|z   |dz   |z   |d          }|| j         z
  }|dv r|dz  }|dv r|dz  }t          j        |d|          }t          j        |d|          }||fS )Nr         int64dtypeleftboth)r<   neither)r   nparangeclip)	r   r   r   r!   r#   r%   offsetendstarts	            r   r*   z$FixedWindowIndexer.get_window_bounds`   s      	T%**&*q0FFFiF
JNV$;TQQQd&&%%%QJE(((1HCgc1j))q*--czr   r+   r,   r-   r.   r/   r0   r   r1   r*   r2   r   r   r4   r4   ]   sZ        ==X#$$ "&"!    %$  r   r4   c                  H    e Zd ZdZ ee          	 	 	 	 	 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"   r#   r$   r%   r   r&   c                >    t          || j        |||| j                  S r   )r   r   r   r)   s         r   r*   z'VariableWindowIndexer.get_window_bounds~   s.     0
 
 	
r   r+   r,   rE   r2   r   r   rG   rG   {   sZ        XXX#$$ "&"!
 
 
 
 %$
 
 
r   rG   c                  d     e Zd ZdZ	 	 	 	 dd fdZ ee          	 	 	 	 	 ddd            Z x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 | NonerB   BaseOffset | Noner   r   c                     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	   
ValueErrorrK   r   rB   )r   r   r   rK   rB   r   	__class__s         r   r   z$VariableOffsetWindowIndexer.__init__   s{     	k<<V<<<%// 	?=>>>
&*-- 	IGHHHr   r   r   r    r!   r"   r#   r$   r%   r&   c                   |t          d          |dk    r,t          j        dd          t          j        dd          fS || j        dnd}|dv }|dv }| j        |d	z
           | j        d         k     rd
}nd	}|| j        z  }	t          j        |d          }
|
                    d
           t          j        |d          }|                    d
           d|
d<   |rd	|d<   nd|d<   t          d          }t          d	|          D ]}| j        |         }||	z
  }|r|t          d	          z  }||
|<   t          |
|d	z
           |          D ]"}| j        |         |z
  |z  }||k    r||
|<    n#| j        ||d	z
                    |z
  |z  }||k    r|s||d	z
           d	z   ||<   n||k    r	|d	z   ||<   n||d	z
           ||<   |s||xx         d	z  cc<   |
|fS )Nz/step not implemented for variable offset windowr   r8   r9   rightr=   )rT   r=   r;   r6   )	r(   r?   emptyrK   rB   fillr   ranger
   )r   r   r   r!   r#   r%   right_closedleft_closedindex_growth_signoffset_diffrD   rC   zeroi	end_boundstart_boundj
start_diffend_diffs                      r   r*   z-VariableOffsetWindowIndexer.get_window_bounds   sp    %&WXXX??8AW---rx/I/I/III > $
 6WWFF!22 00:j1n%
155 " !'$+57333

2hz111a  	CFF CF|| q*%% 	 	A
1I#k1K  'tAww& E!H5Q<++  "jmk9=NN
$$ E!HE % 
3q1u:.:>OOH4QUaAT!!QAQUA   A!czr   )Nr   NN)
r   r   r   r   rK   rL   rB   rM   r   r   r+   r,   )	r-   r.   r/   r0   r   r   r1   r*   __classcell__rR   s   @r   rJ   rJ      s        ! !J *.&*$(        X#$$ "&"!J J J J %$J J J J Jr   rJ   c                  H    e Zd ZdZ ee          	 	 	 	 	 ddd            ZdS )ExpandingIndexerz;Calculate expanding window bounds, mimicking df.expanding()r   Nr   r   r   r    r!   r"   r#   r$   r%   r   r&   c                    t          j        |t           j                  t          j        d|dz   t           j                  fS )Nr9   r6   )r?   zerosr8   r@   r)   s         r   r*   z"ExpandingIndexer.get_window_bounds  s<     HZrx000Iaarx888
 	
r   r+   r,   rE   r2   r   r   rg   rg     sZ        EEX#$$ "&"!
 
 
 
 %$
 
 
r   rg   c                  H    e Zd ZdZ ee          	 	 	 	 	 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"   r#   r$   r%   r   r&   c                    |rt          d          |t          d          |d}t          j        d||d          }|| j        z   }| j        rt          j        |d|          }||fS )Nz.Forward-looking windows can't have center=TruezAForward-looking windows don't support setting the closed argumentr6   r   r8   r9   )rQ   r?   r@   r   rA   )r   r   r   r!   r#   r%   rD   rC   s           r   r*   z+FixedForwardWindowIndexer.get_window_boundsB  s      	OMNNNS   <D	!ZW===d&& 	.'#q*--Cczr   r+   r,   rE   r2   r   r   rk   rk   )  s`         0 X#$$ "&"!    %$  r   rk   c                  f     e Zd ZdZdddedfd fdZ ee          	 	 	 	 	 ddd            Z x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                    |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   Nr2   )rp   rr   copyrt   rO   r   pop)r   r   r   rp   rr   rt   r   rR   s          r   r   zGroupbyIndexer.__init___  s    6  /4",7EMn113332 	
#+//{KK	
 	
 	
 	
 	
 	
 	
r   r   r   r   r    r!   r"   r#   r$   r%   r&   c                   g }g }d}| j                                         D ]\  }	}
| j        (| j                            t	          |
                    }n| j        } | j        d	|| j        d| j        }|                    t          |
          ||||          \  }}|
                    t          j                  }|
                    t          j                  }t          |          t          |          k    s
J d            t          j        ||t          |
          z             }|t          |
          z  }t          j        ||d         dz   g          
                    t          j        d          }|                    |                    t	          |                               |                    |                    t	          |                               t          |          dk    r@t          j        g t          j                  t          j        g t          j                  fS t          j        |          }t          j        |          }||fS )
Nr   rv   z6these should be equal in length from get_window_boundsrU   r6   F)rw   r9   r2   )rp   r   r   taker   rr   r   rt   r*   lenastyper?   r8   r@   appendarrayconcatenate)r   r   r   r!   r#   r%   start_arrays
end_arrayswindow_indices_startr   indicesr   indexerrD   rC   window_indicess                   r   r*   z GroupbyIndexer.get_window_bounds  sb    
  06688 	M 	MLC +".334G4P4PQQ".)d) ' ,  % G
 !22Gk664 JE3 LL**E**RX&&Cu::" "   G  
  Y$&:S\\&I N !CLL0 Y~r8JQ8N7OPPWWu X  N  3 34G4N4N O OPPPn112Ec2J2JKKLLLL|!!8Bbh///"BH1M1M1MMM|,,nZ((czr   )r   r   r   ro   rp   rq   rr   rs   rt   rq   r   r   r+   r,   )
r-   r.   r/   r0   r   r   r   r1   r*   rd   re   s   @r   rn   rn   \  s        WW *.)*'+,7&*"
 "
 "
 "
 "
 "
 "
H X#$$ "&"!2 2 2 2 %$2 2 2 2 2r   rn   c                  H    e Zd ZdZ ee          	 	 	 	 	 ddd            ZdS )ExponentialMovingWindowIndexerz/Calculate ewm window bounds (the entire window)r   Nr   r   r   r    r!   r"   r#   r$   r%   r   r&   c                    t          j        dgt           j                  t          j        |gt           j                  fS )Nr   r9   )r?   r~   r8   r)   s         r   r*   z0ExponentialMovingWindowIndexer.get_window_bounds  s5     x28,,,bh
|28.T.T.TTTr   r+   r,   rE   r2   r   r   r   r     sa        99X#$$ "&"!U U U U %$U U Ur   r   )r0   
__future__r   datetimer   numpyr?   pandas._libs.tslibsr   pandas._libs.window.indexersr   pandas.util._decoratorsr   pandas.core.dtypes.commonr   pandas.core.indexes.datetimesr	   pandas.tseries.offsetsr
   r1   r   r4   rG   rJ   rg   rk   rn   r   r2   r   r   <module>r      s%   R R " " " " " "           * * * * * * I I I I I I , , , , , , 9 9 9 9 9 9 7 7 7 7 7 7 ' ' ' ' ' ' 8," ," ," ," ," ," ," ,"^       <
 
 
 
 
K 
 
 
4    +   D
 
 
 
 
{ 
 
 
$0 0 0 0 0 0 0 0fZ Z Z Z Z[ Z Z ZzU U U U U[ U U U U Ur   