class_docstr: Dataset wraps pandas DataFrame together with ML related metadata.
  
  The Dataset class is containing additional data and methods intended for easily accessing
  metadata relevant for the training or validating of an ML models.
  
  Parameters
  ----------
  df : Any
      An object that can be casted to a pandas DataFrame
       - containing data relevant for the training or validating of a ML models.
  label : t.Union[Hashable, pd.Series, pd.DataFrame, np.ndarray] , default: None
      label column provided either as a string with the name of an existing column in the DataFrame or a label
      object including the label data (pandas Series/DataFrame or a numpy array) that will be concatenated to the
      data in the DataFrame. in case of label data the following logic is applied to set the label name:
  
      - Series: takes the series name or 'target' if name is empty
      - DataFrame: expect single column in the dataframe and use its name
      - numpy: use 'target'
  
  features : t.Optional[t.Sequence[Hashable]] , default: None
      List of names for the feature columns in the DataFrame.
  cat_features : t.Optional[t.Sequence[Hashable]] , default: None
      List of names for the categorical features in the DataFrame. In order to disable categorical.
      features inference, pass cat_features=[]
  index_name : t.Optional[Hashable] , default: None
      Name of the index column in the dataframe. If set_index_from_dataframe_index is True and index_name
      is not None, index will be created from the dataframe index level with the given name. If index levels
      have no names, an int must be used to select the appropriate level by order.
  set_index_from_dataframe_index : bool , default: False
      If set to true, index will be created from the dataframe index instead of dataframe columns (default).
      If index_name is None, first level of the index will be used in case of a multilevel index.
  datetime_name : t.Optional[Hashable] , default: None
      Name of the datetime column in the dataframe. If set_datetime_from_dataframe_index is True and datetime_name
      is not None, date will be created from the dataframe index level with the given name. If index levels
      have no names, an int must be used to select the appropriate level by order.
  set_datetime_from_dataframe_index : bool , default: False
      If set to true, date will be created from the dataframe index instead of dataframe columns (default).
      If datetime_name is None, first level of the index will be used in case of a multilevel index.
  convert_datetime : bool , default: True
      If set to true, date will be converted to datetime using pandas.to_datetime.
  datetime_args : t.Optional[t.Dict] , default: None
      pandas.to_datetime args used for conversion of the datetime column.
      (look at https://pandas.pydata.org/docs/reference/api/pandas.to_datetime.html for more documentation)
  max_categorical_ratio : float , default: 0.01
      The max ratio of unique values in a column in order for it to be inferred as a
      categorical feature.
  max_categories : int , default: None
      The maximum number of categories in a column in order for it to be inferred as a categorical
      feature. if None, uses is_categorical default inference mechanism.
  label_type : str , default: None
      Used to determine the task type. If None, inferred when running a check based on label column and model.
      Possible values are: 'multiclass', 'binary' and 'regression'.
code: def __init__(
      self,
      df: t.Any,
      label: t.Union[
          Hashable, pd.Series, pd.DataFrame, np.ndarray
      ] = None,
      features: t.Optional[t.Sequence[Hashable]] = None,
      cat_features: t.Optional[t.Sequence[Hashable]] = None,
      index_name: t.Optional[Hashable] = None,
      set_index_from_dataframe_index: bool = False,
      datetime_name: t.Optional[Hashable] = None,
      set_datetime_from_dataframe_index: bool = False,
      convert_datetime: bool = True,
      datetime_args: t.Optional[t.Dict] = None,
      max_categorical_ratio: float = 0.01,
      max_categories: int = None,
      label_type: str = None,
      dataset_name: t.Optional[str] = None,
      label_classes=None,
  ):
      if len(df) == 0:
          raise DeepchecksValueError(
              "Can't create a Dataset object with an empty dataframe"
          )
      self._data = pd.DataFrame(df).copy()
  
      # Checking for duplicate columns
      duplicated_columns = [
          key
          for key, value in Counter(self._data.columns).items()
          if value > 1
      ]
      if len(duplicated_columns) >= 1:
          raise DeepchecksValueError(
              f"Data has {len(duplicated_columns)} duplicate columns. "
              "Change the duplicate column names or remove them from the data. "
              f"Duplicate column names: {duplicated_columns}"
          )
  
      # Validations
      if label is None:
          self._label_name = None
      elif isinstance(label, (pd.Series, pd.DataFrame, np.ndarray)):
          if isinstance(label, pd.DataFrame):
              if label.shape[1] != 1:
                  raise DeepchecksValueError(
                      "Provide label as a Series or a DataFrame with a single column."
                  )
              label = label.iloc[:, 0]
          elif isinstance(label, np.ndarray):
              if len(label.shape) > 2:
                  raise DeepchecksValueError(
                      "Label must be either column vector or row vector"
                  )
              elif len(label.shape) == 2:
                  if all(x != 1 for x in label.shape):
                      raise DeepchecksValueError(
                          "Label must be either column vector or row vector"
                      )
                  label = np.squeeze(label)
              label = pd.Series(label)
  
          if label.shape[0] != self._data.shape[0]:
              raise DeepchecksValueError(
                  "Number of samples of label and data must be equal"
              )
          pd.testing.assert_index_equal(self._data.index, label.index)
  
          self._label_name = (
              DEFAULT_LABEL_NAME
              if label.name is None or label.name == 0
              else label.name
          )
          if self._label_name in self._data.columns:
              raise DeepchecksValueError(
                  f'Data has column with name "{self._label_name}", change label column name '
                  f"or provide the column label name as str"
              )
          self._data[self._label_name] = label
  
      elif isinstance(label, Hashable):
          if label not in self._data.columns:
              raise DeepchecksValueError(
                  f"label column {label} not found in dataset columns"
              )
          self._label_name = label
      else:
          raise DeepchecksValueError(
              f"Unsupported type for label: {type(label).__name__}"
          )
  
      # Assert that the requested index can be found
      if not set_index_from_dataframe_index:
          if (
              index_name is not None
              and index_name not in self._data.columns
          ):
              error_message = f"Index column {index_name} not found in dataset columns."
              if index_name == "index":
                  error_message += (
                      " If you attempted to use the dataframe index, set "
                      "set_index_from_dataframe_index to True instead."
                  )
              raise DeepchecksValueError(error_message)
      else:
          if index_name is not None:
              if isinstance(index_name, str):
                  if index_name not in self._data.index.names:
                      raise DeepchecksValueError(
                          f"Index {index_name} not found in dataframe index level names."
                      )
              elif isinstance(index_name, int):
                  if index_name > (len(self._data.index.names) - 1):
                      raise DeepchecksValueError(
                          f"Dataframe index has less levels than {index_name + 1}."
                      )
              else:
                  raise DeepchecksValueError(
                      f"When set_index_from_dataframe_index is True index_name can be None,"
                      f" int or str, but found {type(index_name)}"
                  )
  
      # Assert that the requested datetime can be found
      if not set_datetime_from_dataframe_index:
          if (
              datetime_name is not None
              and datetime_name not in self._data.columns
          ):
              error_message = f"Datetime column {datetime_name} not found in dataset columns."
              if datetime_name == "date":
                  error_message += (
                      " If you attempted to use the dataframe index, "
                      "set set_datetime_from_dataframe_index to True instead."
                  )
              raise DeepchecksValueError(error_message)
      else:
          if datetime_name is not None:
              if isinstance(datetime_name, str):
                  if datetime_name not in self._data.index.names:
                      raise DeepchecksValueError(
                          f"Datetime {datetime_name} not found in dataframe index level names."
                      )
              elif isinstance(datetime_name, int):
                  if datetime_name > (len(self._data.index.names) - 1):
                      raise DeepchecksValueError(
                          f"Dataframe index has less levels than {datetime_name + 1}."
                      )
              else:
                  raise DeepchecksValueError(
                      f"When set_index_from_dataframe_index is True index_name can be None,"
                      f" int or str, but found {type(index_name)}"
                  )
          self._datetime_column = self.get_datetime_column_from_index(
              datetime_name
          )
  
      if features is not None:
          difference = set(features) - set(self._data.columns)
          if len(difference) > 0:
              raise DeepchecksValueError(
                  "Features must be names of columns in dataframe. "
                  f"Features {difference} have not been "
                  "found in input dataframe."
              )
          self._features = list(features)
      else:
          self._features = [
              x
              for x in self._data.columns
              if x
              not in {
                  self._label_name,
                  index_name
                  if not set_index_from_dataframe_index
                  else None,
                  datetime_name
                  if not set_datetime_from_dataframe_index
                  else None,
              }
          ]
  
      if len(set(self._data.index)) != len(self._data.index):
          if set_index_from_dataframe_index:
              raise DeepchecksValueError(
                  "Selected index column has duplicate values."
              )
          else:
              self._data["original_df_index"] = self._data.index
              self._data.index = range(len(self._data.index))
              warnings.warn(
                  "Dataframe index has duplicate indexes, setting index to [0,1..,n-1]."
              )
  
      self._index_name = index_name
      self._set_index_from_dataframe_index = (
          set_index_from_dataframe_index
      )
      self._convert_datetime = convert_datetime
      self._datetime_name = datetime_name
      self._set_datetime_from_dataframe_index = (
          set_datetime_from_dataframe_index
      )
      self._datetime_args = datetime_args or {}
  
      self._max_categorical_ratio = max_categorical_ratio
      self._max_categories = max_categories
  
      if isinstance(dataset_name, str) or (dataset_name is None):
          self.name = dataset_name
      else:
          raise DeepchecksValueError(
              "The dataset_name parameter accepts a string or None."
          )
  
      if self._label_name in self.features:
          raise DeepchecksValueError(
              f"label column {self._label_name} can not be a feature column"
          )
  
      if self._datetime_name in self.features:
          raise DeepchecksValueError(
              f"datetime column {self._datetime_name} can not be a feature column"
          )
  
      if self._index_name in self.features:
          raise DeepchecksValueError(
              f"index column {self._index_name} can not be a feature column"
          )
  
      if cat_features is not None:
          if set(cat_features).intersection(set(self._features)) != set(
              cat_features
          ):
              raise DeepchecksValueError(
                  "Categorical features must be a subset of features. "
                  f"Categorical features {set(cat_features) - set(self._features)} "
                  "have not been found in feature list."
              )
          self._cat_features = list(cat_features)
      else:
          self._cat_features = self._infer_categorical_features(
              self._data,
              max_categorical_ratio=max_categorical_ratio,
              max_categories=max_categories,
              columns=self._features,
          )
  
      if (
          (self._datetime_name is not None)
          or self._set_datetime_from_dataframe_index
      ) and convert_datetime:
          if self._set_datetime_from_dataframe_index:
              self._datetime_column = pd.to_datetime(
                  self._datetime_column, **self._datetime_args
              )
          else:
              self._data[self._datetime_name] = pd.to_datetime(
                  self._data[self._datetime_name], **self._datetime_args
              )
  
      if label_type in ["classification_label", "regression_label"]:
          warnings.warn(
              f"{label_type} value for label type is deprecated, allowed task types are multiclass,"
              f" binary and regression.",
              DeprecationWarning,
              stacklevel=2,
          )
          self._label_type = (
              TaskType.REGRESSION
              if label_type == "regression_label"
              else TaskType.MULTICLASS
          )
      elif label_type in [task.value for task in TaskType]:
          self._label_type = TaskType(label_type)
      elif label_type is not None:
          raise DeepchecksValueError(
              f"allowed value for label type are {[task.value for task in TaskType]},"
              f" received {label_type}."
          )
      else:
          self._label_type = None
  
      if label_classes is not None:
          warnings.warn(
              "label_classes parameter is deprecated, use model_classes parameter on a check run function "
              "instead.",
              DeprecationWarning,
              stacklevel=2,
          )
  
      unassigned_cols = [
          col for col in self._features if col not in self._cat_features
      ]
      self._numerical_features = infer_numerical_features(
          self._data[unassigned_cols]
      )
  
imports: import typing
  import warnings
  from collections import Counter
  import numpy
  import pandas
  from IPython.display import HTML, display_html
  from pandas.api.types import infer_dtype
  from sklearn.model_selection import train_test_split
  from typing_extensions import Literal
  from deepchecks.core.errors import DatasetValidationError, DeepchecksNotSupportedError, DeepchecksValueError
  from deepchecks.tabular.utils.task_type import TaskType
  from deepchecks.utils.dataframes import select_from_dataframe
  from deepchecks.utils.logger import get_logger
  from deepchecks.utils.strings import get_docs_link
  from deepchecks.utils.type_inference import infer_categorical_features, infer_numerical_features
  from deepchecks.utils.typing import Hashable
label_desc: Use image node_id 1 to create a new Dataset object  with example: obj = Dataset(df, label, features, cat_features, index_name, set_index_from_dataframe_index, datetime_name, set_datetime_from_dataframe_index, convert_datetime, datetime_args, max_categorical_ratio, max_categories, label_type, dataset_name, label_classes)