
    iV[                    `   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  ed       G d d             Z G d de      Z G d de      Z ed       G d de             Z G d de      Z ed       G d de             Z G d de      Z G d de      Zy)zLIndexer objects for computing start/end window bounds for rolling operations    )annotations)	timedeltaN)
BaseOffset) calculate_variable_window_bounds)
set_module)ensure_platform_int)DatetimeIndex)Nanozpandas.api.indexersc                  P    e Zd ZdZ	 d	 	 	 	 	 ddZ	 	 	 	 	 d	 	 	 	 	 	 	 	 	 	 	 ddZy)	BaseIndexera  
    Base class for window bounds calculations.

    Parameters
    ----------
    index_array : np.ndarray, default None
        Array-like structure representing the indices for the data points.
        If None, the default indices are assumed. This can be useful for
        handling non-uniform indices in data, such as in time series
        with irregular timestamps.
    window_size : int, default 0
        Size of the moving window. This is the number of observations used
        for calculating the statistic. The default is to consider all
        observations within the window.
    **kwargs
        Additional keyword arguments passed to the subclass's methods.

    See Also
    --------
    DataFrame.rolling : Provides rolling window calculations on dataframe.
    Series.rolling : Provides rolling window calculations on series.

    Examples
    --------
    >>> from pandas.api.indexers import BaseIndexer
    >>> class CustomIndexer(BaseIndexer):
    ...     def get_window_bounds(self, num_values, min_periods, center, closed, step):
    ...         start = np.arange(num_values, dtype=np.int64)
    ...         end = np.arange(num_values, dtype=np.int64) + 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
    Nc                j    || _         || _        |j                         D ]  \  }}t        | ||        y )N)index_arraywindow_sizeitemssetattr)selfr   r   kwargskeyvalues         Y/app/cer_product_mecsu/.venv/lib/python3.12/site-packages/pandas/core/indexers/objects.py__init__zBaseIndexer.__init__?   s9     '& ,,. 	&JCD#u%	&    c                    t         )T  
        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
        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
        )NotImplementedErrorr   
num_valuesmin_periodscenterclosedsteps         r   get_window_boundszBaseIndexer.get_window_boundsH   s    B "!r   )Nr   )r   np.ndarray | Noner   intreturnNoner   NNNNr   r$   r   
int | Noner   zbool | Noner    z
str | Noner!   r)   r%   ztuple[np.ndarray, np.ndarray])__name__
__module____qualname____doc__r   r"    r   r   r   r      s|    'T IJ&,&BE&	& "&"!!"!"  !" 	!"
 !" !" 
'!"r   r   c                  :    e Zd ZdZ	 	 	 	 	 d	 	 	 	 	 	 	 	 	 	 	 ddZy)FixedWindowIndexerz3Creates window boundaries that are of fixed length.Nc                8   |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 )r   r         int64dtypeleftboth)r8   neither)r   nparangeclip)	r   r   r   r   r    r!   offsetendstarts	            r   r"   z$FixedWindowIndexer.get_window_boundso   s    B T%%*&&*q0FFiiF
JNV$;TQd&&&%%QJE((1HCggc1j)q*-czr   r'   r(   r*   r+   r,   r-   r"   r.   r   r   r0   r0   l   sU    = "&"!00  0 	0
 0 0 
'0r   r0   c                  :    e Zd ZdZ	 	 	 	 	 d	 	 	 	 	 	 	 	 	 	 	 ddZy)VariableWindowIndexerzNCreates window boundaries that are of variable length, namely for time series.Nc                    | j                   J t        | j                         x}|k  rt        d| d| d      t        || j                  |||| j                         S )r   z\Variable rolling window requires the index to be at least as long as the 'other' index. Got z < z\. Please align 'other' to the rolling object's index using reindex_like() or similar method.)r   len
ValueErrorr   r   )r   r   r   r   r    r!   index_lengths          r   r"   z'VariableWindowIndexer.get_window_bounds   s    B +++ 0 011LZ?--9N#j\ J44  0
 	
r   r'   r(   rA   r.   r   r   rC   rC      sU    X "&"!2
2
  2
 	2

 2
 2
 
'2
r   rC   c                  j     e Zd ZdZ	 	 	 	 d	 	 	 	 	 	 	 	 	 d fdZ	 	 	 	 	 d	 	 	 	 	 	 	 	 	 	 	 ddZ xZS )VariableOffsetWindowIndexera  
    Calculate window boundaries based on a non-fixed offset such as a BusinessDay.

    Parameters
    ----------
    index_array : np.ndarray, default 0
        Array-like structure specifying the indices for data points.
        This parameter is currently not used.

    window_size : int, optional, default 0
        Specifies the number of data points in each window.
        This parameter is currently not used.

    index : DatetimeIndex, optional
        ``DatetimeIndex`` of the labels of each observation.

    offset : BaseOffset, optional
        ``DateOffset`` representing the size of the window.

    **kwargs
        Additional keyword arguments passed to the parent class ``BaseIndexer``.

    See Also
    --------
    api.indexers.BaseIndexer : Base class for all indexers.
    DataFrame.rolling : Rolling window calculations on DataFrames.
    offsets : Module providing various time offset classes.

    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
    c                    t        |   ||fi | t        |t              st	        d      || _        t        |t              st	        d      || _        y )Nzindex must be a DatetimeIndex.z(offset must be a DateOffset-like object.)superr   
isinstancer	   rF   indexr   r>   )r   r   r   rM   r>   r   	__class__s         r   r   z$VariableOffsetWindowIndexer.__init__  sS     	k<V<%/=>>
&*-GHH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      }
|
j                  d
       t        j                  |d      }|j                  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  }||kD  s||
|<    n | j                  ||d	z
        |z
  |z  }||k(  r|s||d	z
     d	z   ||<   n||k  r	|d	z   ||<   n||d	z
     ||<   |r||xx   d	z  cc<    |
|fS )r   z/step not implemented for variable offset windowr   r4   r5   rightr9   )rP   r9   r7   r2   )	r   r;   emptyrM   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_diffs                      r   r"   z-VariableOffsetWindowIndexer.get_window_bounds(  s!   B %&WXX?88AW-rxx/III > $

 6WFF!22 00::j1n%

15 " !'$++573

2hhz1a CF CF| q*% 	A

1I#k1K tAw& E!H5Q<+ "jjmk9=NN
$ E!H	 

3q1u:.:>OOH4QUaAT!QAQUA  A!;	> czr   )Nr   NN)
r   r#   r   r$   rM   zDatetimeIndex | Noner>   zBaseOffset | Noner%   r&   r'   r(   )r*   r+   r,   r-   r   r"   __classcell__rN   s   @r   rI   rI      s    :| *.&*$(&  $	
 " 
$ "&"!cc  c 	c
 c c 
'cr   rI   c                  :    e Zd ZdZ	 	 	 	 	 d	 	 	 	 	 	 	 	 	 	 	 ddZy)ExpandingIndexerz;Calculate expanding window bounds, mimicking df.expanding()Nc                    t        j                  |t         j                        t        j                  d|dz   t         j                        fS )r   r5   r2   )r;   zerosr4   r<   r   s         r   r"   z"ExpandingIndexer.get_window_bounds  s9    D HHZrxx0IIaarxx8
 	
r   r'   r(   rA   r.   r   r   rc   rc     sU    E "&"!$
$
  $
 	$

 $
 $
 
'$
r   rc   c                  :    e Zd ZdZ	 	 	 	 	 d	 	 	 	 	 	 	 	 	 	 	 ddZy)FixedForwardWindowIndexera  
    Creates window boundaries for fixed-length windows that include the current row.

    Parameters
    ----------
    index_array : np.ndarray, default None
        Array-like structure representing the indices for the data points.
        If None, the default indices are assumed. This can be useful for
        handling non-uniform indices in data, such as in time series
        with irregular timestamps.
    window_size : int, default 0
        Size of the moving window. This is the number of observations used
        for calculating the statistic. The default is to consider all
        observations within the window.
    **kwargs
        Additional keyword arguments passed to the subclass's methods.

    See Also
    --------
    DataFrame.rolling : Provides rolling window calculations.
    api.indexers.VariableWindowIndexer : Calculate window bounds based on
        variable-sized windows.

    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
    Nc                    |rt        d      |t        d      |d}t        j                  d||d      }|| j                  z   }| j                  rt        j                  |d|      }||fS )r   z.Forward-looking windows can't have center=TruezAForward-looking windows don't support setting the closed argumentr2   r   r4   r5   )rF   r;   r<   r   r=   )r   r   r   r   r    r!   r@   r?   s           r   r"   z+FixedForwardWindowIndexer.get_window_bounds  s    B MNNS  <D		!ZW=d&&&''#q*-Cczr   r'   r(   rA   r.   r   r   rg   rg     sX    *\ "&"!//  / 	/
 / / 
'/r   rg   c                  p     e Zd ZdZdddedf	 	 	 	 	 	 	 	 	 	 	 d fdZ	 	 	 	 	 d	 	 	 	 	 	 	 	 	 	 	 ddZ xZS )	GroupbyIndexerzMCalculate bounds to compute groupby rolling, mimicking df.groupby().rolling()Nr   c                    |xs i | _         || _        |r|j                         ni | _        t	        |   d|| j                  j                  d|      d| y)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.   )groupby_indiceswindow_indexercopyindexer_kwargsrK   r   pop)r   r   r   rm   rn   rp   r   rN   s          r   r   zGroupbyIndexer.__init__  sd    6  /4",7En1132 	
#++//{K	
 	
r   c                   g }g }d}| j                   j                         D ]  }	| j                  %| j                  j                  t	        |	            }
n| j                  }
 | j
                  d	|
| j                  d| j                  }|j                  t        |	      ||||      \  }}|j                  t        j                        }|j                  t        j                        }t        |      t        |      k(  sJ d       t        j                  ||t        |	      z         }|t        |	      z  }t        j                  ||d   dz   g      j                  t        j                  d      }|j                  |j                  t	        |                   |j                  |j                  t	        |                    t        |      dk(  rJt        j                  g t        j                        t        j                  g t        j                        fS t        j                   |      }t        j                   |      }||fS )
r   r   rl   z6these should be equal in length from get_window_boundsrQ   r2   F)ro   r5   r.   )rm   valuesr   taker   rn   r   rp   r"   rE   astyper;   r4   r<   appendarrayconcatenate)r   r   r   r   r    r!   start_arrays
end_arrayswindow_indices_startindicesr   indexerr@   r?   window_indicess                  r   r"   z GroupbyIndexer.get_window_bounds?  s   H 
 ++224 	MG +"..334G4PQ"..)d)) ' ,, %%G
 !22Gk664JE3 LL*E**RXX&Cu:S) H)
  YY$&:S\&IN !CL0 YY~r8JQ8N7OPWWu X N  3 34G4N OPn112Ec2JKL?	M@ |!88Bbhh/"BHH1MMM|,nnZ(czr   )r   r#   r   zint | BaseIndexerrm   dict | Nonern   ztype[BaseIndexer]rp   r   r%   r&   r'   r(   )r*   r+   r,   r-   r   r   r"   r`   ra   s   @r   rj   rj     s    W *.)*'+,7&*"
&"
 '"
 %	"

 *"
 $"
 
"
L "&"!KK  K 	K
 K K 
'Kr   rj   c                  :    e Zd ZdZ	 	 	 	 	 d	 	 	 	 	 	 	 	 	 	 	 ddZy)ExponentialMovingWindowIndexerz/Calculate ewm window bounds (the entire window)Nc                    t        j                  dgt         j                        t        j                  |gt         j                        fS )r   r   r5   )r;   rw   r4   r   s         r   r"   z0ExponentialMovingWindowIndexer.get_window_bounds  s2    B xx288,bhh
|288.TTTr   r'   r(   rA   r.   r   r   r   r     s\    9 "&"!!U!U  !U 	!U
 !U !U 
'!Ur   r   )r-   
__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
   r   r0   rC   rI   rc   rg   rj   r   r.   r   r   <module>r      s    R "   * I . 9 7 ' !"T" T" #T"n3 3l5
K 5
p !"p+ p #pf'
{ '
T !"\ \ #\~r[ rj$U[ $Ur   