class_docstr: Sliding window time series split.
  
  Create `n_splits` folds with an as equally possible size through a smart variant of a brute force search.
  Groups parameter in `.split()` method should be filled with the time groups (e.g. years)
  
  If `n_splits` is 3 ("*" = train, "x" = test):
  
  ```console
  * * * x x x - - - - -
  - - - * * * x x x - -
  - - - - - - * * * x x
  ```
  
  Parameters
  ----------
  n_splits : int
      Amount of (train, test) splits to generate.
class_docstr_tok: ["Sliding","window","time","series","split",".","Create","`","n_splits","`","folds","with","an","as","equally","possible","size","through","a","smart","variant","of","a","brute","force","search",".","Groups","parameter","in","`",".split","(",")","`","method","should","be","filled","with","the","time","groups","(","e.g",".","years",")","If","`","n_splits","`","is","3","(","``","*","''","=","train",",","``","x","''","=","test",")",":","``","`","console","*","*","*","x","x","x","-","-","-","-","-","-","-","-","*","*","*","x","x","x","-","-","-","-","-","-","-","-","*","*","*","x","x","``","`","Parameters","--","--","--","--","--","n_splits",":","int","Amount","of","(","train",",","test",")","splits","to","generate","."]
docstr: Calculate an approximate first and last split point to reduce the amount of options during a brute force
  search.
  
  Parameters
  ----------
  X : array-like of shape (n_samples, n_features), default=None
      Ignored, present for compatibility.
  y : array-like of shape (n_samples,), default=None
      Ignored, present for compatibility.
  groups : array-like of shape (n_samples,), default=None
      Array with groups.
  
  Returns
  -------
  tuple[int, int]
      Approximate first and last split indexes.
docstr_tok: ["Calculate","an","approximate","first","and","last","split","point","to","reduce","the","amount","of","options","during","a","brute","force","search",".","Parameters","--","--","--","--","--","X",":","array-like","of","shape","(","n_samples",",","n_features",")",",","default=None","Ignored",",","present","for","compatibility",".","y",":","array-like","of","shape","(","n_samples",",",")",",","default=None","Ignored",",","present","for","compatibility",".","groups",":","array-like","of","shape","(","n_samples",",",")",",","default=None","Array","with","groups",".","Returns","--","--","--","-","tuple","[","int",",","int","]","Approximate","first","and","last","split","indexes","."]
code: def _calc_first_and_last_split_index(
      self, X=None, y=None, groups=None
  ):
      """Calculate an approximate first and last split point to reduce the amount of options during a brute force
      search.
  
      Parameters
      ----------
      X : array-like of shape (n_samples, n_features), default=None
          Ignored, present for compatibility.
      y : array-like of shape (n_samples,), default=None
          Ignored, present for compatibility.
      groups : array-like of shape (n_samples,), default=None
          Array with groups.
  
      Returns
      -------
      tuple[int, int]
          Approximate first and last split indexes.
      """
  
      # get the counts (=amount of rows) for each group
      self._grouped_df = (
          pd.DataFrame(np.array(groups))
          .rename(columns={0: "index"})
          .groupby("index")
          .size()
          .sort_index()
          .to_frame()
          .rename(columns={0: "observations"})
      )
  
      # set the ideal group_size and reduce it to 90% to have some leverage
      self._ideal_group_size = np.sum(
          self._grouped_df["observations"]
      ) / (self.n_splits + 1)
      init_ideal_group_size = self._ideal_group_size * 0.9
  
      # initialize the index of the first split, to reduce the amount of possible index split options
      first_split_index = (
          self._grouped_df.assign(
              cumsum_obs=lambda df: df["observations"].cumsum()
          )
          .assign(
              group_id=lambda df: (df["cumsum_obs"] - 1)
              // init_ideal_group_size
          )
          .reset_index()
          .loc[lambda df: df["group_id"] != 0]
          .iloc[0]
          .name
      )
      # initialize the index of the last split point, to reduce the amount of possible index split options
      last_split_index = len(self._grouped_df) - (
          self._grouped_df.assign(
              observations=lambda df: df["observations"].values[::-1],
              cumsum_obs=lambda df: df["observations"].cumsum(),
          )
          .reset_index()
          .assign(
              group_id=lambda df: (df["cumsum_obs"] - 1)
              // init_ideal_group_size
          )
          .loc[lambda df: df["group_id"] != 0]
          .iloc[0]
          .name
          - 1
      )
      return first_split_index, last_split_index
  
imports: import numbers
  from datetime import timedelta
  from itertools import combinations
  from warnings import warn
  import numpy
  import pandas
  from sklearn.exceptions import NotFittedError
  from sklearn.model_selection._split import _BaseKFold, check_array
  from sklearn.utils.validation import indexable
  from sklego.base import Clusterer
  from sklego.common import sliding_window
label_desc: Use image node_id 7 for calling the GroupTimeSeriesSplit obj's underlying member method code with example usage: obj._calc_first_and_last_split_index(X, y, groups) and returns: first_split_index,  last_split_index