code: def stability_curve_time_space_splitter(
      train_data: pd.DataFrame,
      training_time_limit: DateType,
      space_column: str,
      time_column: str,
      freq: str = "M",
      space_hold_percentage: float = 0.5,
      random_state: int = None,
      min_samples: int = 1000,
  ) -> SplitterReturnType:
      """
      Splits the data into temporal buckets given by the specified frequency.
      Training set is fixed before hold out and uses a rolling window hold out set.
      Each fold moves the hold out further into the future.
      Useful to see how model performance degrades as the training data gets more
      outdated. Folds are made so that NONE of the IDs in the holdout appears in
      the training set.
  
      Parameters
      ----------
      train_data : pandas.DataFrame
          A Pandas' DataFrame that will be split for stability curve estimation.
  
      training_time_limit : str
          The Date String for the end of the testing period. Should be of the same
          format as `time_column`
  
      space_column : str
          The name of the ID column of `train_data`
  
      time_column : str
          The name of the Date column of `train_data`
  
      freq : str
          The temporal frequency.
          See: http://pandas.pydata.org/pandas-docs/stable/timeseries.html#offset-aliases
  
      space_hold_percentage : float
          The proportion of hold out IDs
  
      random_state : int
          A seed for the random number generator for ID sampling across train and
          hold out sets.
  
      min_samples : int
          The minimum number of samples required in the split to keep the split.
      """
      train_data = train_data.reset_index()
  
      rng = check_random_state(random_state)
  
      train_time = train_data[
          train_data[time_column] <= training_time_limit
      ][time_column]
      train_index = train_time.index.values
      train_space = train_data.iloc[train_index][space_column].unique()
  
      held_space = rng.choice(
          train_space,
          int(len(train_space) * space_hold_percentage),
          replace=False,
      )
  
      test_data = train_data[
          (train_data[time_column] > training_time_limit)
          & (~train_data[space_column].isin(held_space))
      ]
      train_index = train_data[
          (train_data[time_column] <= training_time_limit)
          & (train_data[space_column].isin(held_space))
      ].index.values
  
      first_test_moment = test_data[time_column].min()
      last_test_moment = test_data[time_column].max()
  
      logs, test_indexes = _get_sc_test_fold_idx_and_logs(
          test_data,
          train_time,
          time_column,
          first_test_moment,
          last_test_moment,
          min_samples,
          freq,
      )
  
      # From "list of dicts" to "dict of lists" hack:
      logs = [{k: [dic[k] for dic in logs] for k in logs[0]}]
  
      # Flatten test_indexes:
      flattened_test_indices = list(chain.from_iterable(test_indexes))
  
      return [(train_index, flattened_test_indices)], logs
  
imports: import operator
  from datetime import datetime, timedelta
  from itertools import chain, repeat, starmap
  from typing import Callable, Iterable, List, Tuple, Union
  import numpy
  import pandas
  from sklearn.model_selection import GroupKFold, KFold, StratifiedKFold
  from sklearn.utils import check_random_state
  from toolz.curried import curry, partial, pipe, assoc, accumulate, map, filter
  from fklearn.common_docstrings import splitter_return_docstring
  from fklearn.types import DateType, LogType, SplitterReturnType
label_desc: Use image node_id 14 for calling a global function with example usage: stability_curve_time_space_splitter(train_data, training_time_limit, space_column, time_column, freq, space_hold_percentage, random_state, min_samples) and returns: list,  logs