docs: def _normalize_input_to_internal_representation(timeseries_container, column_id, column_sort, column_kind, column_value):
      """
      Try to transform any given input to the internal representation of time series, which is a flat DataFrame
      (the first format from see :ref:`data-formats-label`).
  
      This function can transform pandas DataFrames in different formats or dictionaries into the internal format
      that we use. It should not be called by the user.
  
      :param timeseries_container: a pandas DataFrame or a dictionary. The required shape/form of the object depends on
          the rest of the passed arguments.
      :type timeseries_container: pandas.DataFrame or dict
      :param column_id: it must be present in the pandas DataFrame or in all DataFrames in the dictionary.
          It is not allowed to have NaN values in this column.
      :type column_id: basestring
      :param column_sort: if not None, sort the rows by this column. It is not allowed to
          have NaN values in this column.
      :type column_sort: basestring or None
      :param column_kind: It can only be used when passing a pandas DataFrame (the dictionary is already assumed to be
          grouped by the kind). Is must be present in the DataFrame and no NaN values are allowed. The DataFrame
          will be grouped by the values in the kind column and each group will be one entry in the resulting
          mapping.
          If the kind column is not passed, it is assumed that each column in the pandas DataFrame (except the id or
          sort column) is a possible kind and the DataFrame is split up into as many DataFrames as there are columns.
          It is not allowed to have a value column then.
      :type column_kind: basestring or None
      :param column_value: If it is given, it must be present and not-NaN on the pandas DataFrames (or all pandas
          DataFrames in the dictionaries). If it is None, the kind column must also be none.
      :type column_value: basestring or None
  
      :return: A tuple of 4 elements: the normalized DataFrame, the name of the id column, the name of the value column
               and the name of the value column
      :rtype: (pd.DataFrame, basestring, basestring, basestring)
      :raise: ``ValueError`` when the passed combination of parameters is wrong or does not fit to the input DataFrame
              or dict.
      """
      # Also make it possible to have a dict as an input
      if isinstance(timeseries_container, dict):
          if column_kind is not None:
              raise ValueError("You passed in a dictionary and gave a column name for the kind. Both are not possible.")
  
          column_kind = "_variables"
  
          timeseries_container = {key: df.copy() for key, df in timeseries_container.items()}
  
          for kind, df in timeseries_container.items():
              df[column_kind] = kind
  
          timeseries_container = pd.concat(timeseries_container.values())
          gc.collect()
  
      # Check ID column
      if column_id is None:
          raise ValueError("You have to set the column_id which contains the ids of the different time series")
  
      if column_id not in timeseries_container.columns:
          raise AttributeError("The given column for the id is not present in the data.")
  
      if timeseries_container[column_id].isnull().any():
          raise ValueError("You have NaN values in your id column.")
  
      # Check sort column
      if column_sort is not None:
          if timeseries_container[column_sort].isnull().any():
              raise ValueError("You have NaN values in your sort column.")
  
      # Check that either kind and value is None or both not None.
      if column_kind is None and column_value is not None:
          column_kind = "_variables"
          timeseries_container = timeseries_container.copy()
          timeseries_container[column_kind] = column_value
      if column_kind is not None and column_value is None:
          raise ValueError("If passing the kind, you also have to pass the value.")
  
      if column_kind is None and column_value is None:
          if column_sort is not None:
              column_kind = "_variables"
              column_value = "_values"
              sort = timeseries_container[column_sort].values
              timeseries_container = pd.melt(timeseries_container.drop(column_sort, axis=1),
                                             id_vars=[column_id],
                                             value_name=column_value, var_name=column_kind)
              timeseries_container[column_sort] = np.repeat(sort, (len(timeseries_container) // len(sort)))
          else:
              column_kind = "_variables"
              column_value = "_values"
              column_sort = "_sort"
              sort = range(len(timeseries_container))
              timeseries_container = pd.melt(timeseries_container, id_vars=[column_id],
                                             value_name=column_value, var_name=column_kind)
              timeseries_container[column_sort] = np.repeat(sort, (len(timeseries_container) // len(sort)))
  
      # Check kind column
      if column_kind not in timeseries_container.columns:
          raise AttributeError("The given column for the kind is not present in the data.")
  
      if timeseries_container[column_kind].isnull().any():
          raise ValueError("You have NaN values in your kind column.")
  
      # Check value column
      if column_value not in timeseries_container.columns:
          raise ValueError("The given column for the value is not present in the data.")
  
      if timeseries_container[column_value].isnull().any():
          raise ValueError("You have NaN values in your value column.")
  
      if column_sort:
          timeseries_container = timeseries_container.sort_values([column_id, column_kind, column_sort])
          timeseries_container = timeseries_container.drop(column_sort, axis=1)
      else:
          timeseries_container = timeseries_container.sort_values([column_id, column_kind])
  
      # The kind columns should always be of type "str" to make the inference of feature settings later in `from_columns`
      # work
      timeseries_container[column_kind] = timeseries_container[column_kind].astype(str)
      return timeseries_container, column_id, column_kind, column_value