class_docstr: Data Shuffling step that shuffles data inputs, and expected_outputs at the same time.
  
  .. code-block:: python
  
      p = Pipeline([
          TrainOnlyWrapper(DataShuffler(seed=42, increment_seed_after_each_fit=True)),
          EpochRepeater(ForecastingPipeline(), epochs=EPOCHS, repeat_in_test_mode=False)
      ])
  
  .. warning::
      You probably always want to wrap this step by a :class:`TrainOnlyWrapper`
  
  .. seealso::
      :class:`EpochRepeater`,
      :class:`~neuraxle.steps.flow.TrainOnlyWrapper`,
      :class:`~neuraxle.steps.output_handlers.InputAndOutputTransformerMixin`,
      :class:`~neuraxle.base.BaseStep`
class_docstr_tok: ["Data","Shuffling","step","that","shuffles","data","inputs",",","and","expected_outputs","at","the","same","time",".","..","code-block",":",":","python","p","=","Pipeline","(","[","TrainOnlyWrapper","(","DataShuffler","(","seed=42",",","increment_seed_after_each_fit=True",")",")",",","EpochRepeater","(","ForecastingPipeline","(",")",",","epochs=EPOCHS",",","repeat_in_test_mode=False",")","]",")","..","warning",":",":","You","probably","always","want","to","wrap","this","step","by","a",":","class",":","`","TrainOnlyWrapper","`","..","seealso",":",":",":","class",":","`","EpochRepeater","`",",",":","class",":","`","~neuraxle.steps.flow.TrainOnlyWrapper","`",",",":","class",":","`","~neuraxle.steps.output_handlers.InputAndOutputTransformerMixin","`",",",":","class",":","`","~neuraxle.base.BaseStep","`"]
docstr: Shuffle data inputs, and expected outputs.
  
  :param data_inputs: (data inputs, expected outputs) tuple to shuffle
  :return:
docstr_tok: ["Shuffle","data","inputs",",","and","expected","outputs",".",":","param","data_inputs",":","(","data","inputs",",","expected","outputs",")","tuple","to","shuffle",":","return",":"]
code: def transform(self, data_inputs):
      """
      Shuffle data inputs, and expected outputs.
  
      :param data_inputs: (data inputs, expected outputs) tuple to shuffle
      :return:
      """
      if self.increment_seed_after_each_fit:
          self.seed += 1
  
      ids, di, eo = data_inputs
  
      ids_is_none = ids is None
      if ids_is_none:
          ids = range(len(di))
  
      data = list(zip(ids, di, eo))
      random.Random(self.seed).shuffle(data)
      (
          ids_shuffled,
          data_inputs_shuffled,
          expected_outputs_shuffled,
      ) = list(zip(*data))
  
      return (
          ids_shuffled,
          list(data_inputs_shuffled),
          list(expected_outputs_shuffled),
      )
  
imports: import random
  from operator import attrgetter
  from typing import Iterable, List, Tuple
  from neuraxle.base import BaseStep, BaseTransformer
  from neuraxle.base import ExecutionContext
  from neuraxle.base import ForceHandleOnlyMixin, MetaStep
  from neuraxle.data_container import DACT, _inner_concatenate_np_array
  from neuraxle.pipeline import Pipeline
  from neuraxle.steps.flow import TrainOnlyWrapper
  from neuraxle.steps.output_handlers import IdsAndInputAndOutputTransformerMixin
label_desc: Use image node_id 2 for calling the DataShuffler obj's underlying member method code with example usage: obj.transform(data_inputs) and returns: ids_shuffled,  list,  list