code: def __resample(self):
      # self.logger.info("Resampling etalon")
      # Resample imbalanced target. Only train segment (without eval_set)
      if EVAL_SET_INDEX in self.data.columns:
          train_segment = self.data[self.data[EVAL_SET_INDEX] == 0]
      else:
          train_segment = self.data
  
      if self.task_type == ModelTaskType.MULTICLASS or (
          self.task_type == ModelTaskType.BINARY
          and len(train_segment) > self.MIN_SAMPLE_THRESHOLD
      ):
          count = len(train_segment)
          min_class_count = count
          min_class_value = None
          target_column = self.etalon_def_checked.get(
              FileColumnMeaningType.TARGET.value, ""
          )
          target = train_segment[target_column].copy()
          target_classes_count = target.nunique()
  
          if target_classes_count > self.MAX_MULTICLASS_CLASS_COUNT:
              msg = bundle.get(
                  "dataset_to_many_multiclass_targets"
              ).format(
                  target_classes_count, self.MAX_MULTICLASS_CLASS_COUNT
              )
              self.logger.warning(msg)
              raise ValidationError(msg)
  
          unique_target = target.unique()
          for v in list(unique_target):  # type: ignore
              current_class_count = len(train_segment.loc[target == v])
              if current_class_count < min_class_count:
                  min_class_count = current_class_count
                  min_class_value = v
  
          if min_class_count < self.MIN_TARGET_CLASS_ROWS:
              msg = bundle.get("dataset_rarest_class_less_min").format(
                  min_class_value,
                  min_class_count,
                  self.MIN_TARGET_CLASS_ROWS,
              )
              self.logger.warning(msg)
              raise ValidationError(msg)
  
          min_class_percent = (
              self.IMBALANCE_THESHOLD / target_classes_count
          )
          min_class_threshold = min_class_percent * count
  
          if min_class_count < min_class_threshold:
              msg = bundle.get(
                  "dataset_rarest_class_less_threshold"
              ).format(
                  min_class_value,
                  min_class_count,
                  min_class_threshold,
                  min_class_percent * 100,
              )
              self.logger.warning(msg)
              print(msg)
              self.warning_counter.increment()
  
              train_segment = train_segment.copy().sort_values(
                  by=SYSTEM_RECORD_ID
              )
              if self.task_type == ModelTaskType.MULTICLASS:
                  # Sort classes by rows count and find 25% quantile class
                  classes = target.value_counts().index
                  quantile25_idx = int(0.75 * len(classes))
                  quantile25_class = classes[quantile25_idx]
                  count_of_quantile25_class = len(
                      target[target == quantile25_class]
                  )
                  msg = bundle.get("imbalance_multiclass").format(
                      quantile25_class, count_of_quantile25_class
                  )
                  self.logger.warning(msg)
                  print(msg)
                  # 25% and lower classes will stay as is. Higher classes will be downsampled
                  parts = []
                  for class_idx in range(quantile25_idx):
                      sampled = train_segment[
                          train_segment[target_column]
                          == classes[class_idx]
                      ].sample(
                          n=count_of_quantile25_class,
                          random_state=self.random_state,
                      )
                      parts.append(sampled)
                  for class_idx in range(quantile25_idx, len(classes)):
                      parts.append(
                          train_segment[
                              train_segment[target_column]
                              == classes[class_idx]
                          ]
                      )
                  resampled_data = pd.concat(parts)
              elif (
                  self.task_type == ModelTaskType.BINARY
                  and min_class_count < self.MIN_SAMPLE_THRESHOLD / 2
              ):
                  minority_class = train_segment[
                      train_segment[target_column] == min_class_value
                  ]
                  majority_class = train_segment[
                      train_segment[target_column] != min_class_value
                  ]
                  sampled_majority_class = majority_class.sample(
                      n=self.MIN_SAMPLE_THRESHOLD - min_class_count,
                      random_state=self.random_state,
                  )
                  resampled_data = train_segment[
                      (
                          train_segment[SYSTEM_RECORD_ID].isin(
                              minority_class[SYSTEM_RECORD_ID]
                          )
                      )
                      | (
                          train_segment[SYSTEM_RECORD_ID].isin(
                              sampled_majority_class[SYSTEM_RECORD_ID]
                          )
                      )
                  ]
              else:
                  sampler = RandomUnderSampler(
                      random_state=self.random_state
                  )
                  X = train_segment[SYSTEM_RECORD_ID]
                  X = X.to_frame(SYSTEM_RECORD_ID)
                  new_x, _ = sampler.fit_resample(X, target)  # type: ignore
                  resampled_data = train_segment[
                      train_segment[SYSTEM_RECORD_ID].isin(
                          new_x[SYSTEM_RECORD_ID]
                      )
                  ]
  
              self.data = resampled_data
              self.logger.info(
                  f"Shape after rebalance resampling: {self.data.shape}"
              )
              self.imbalanced = True
  
      # Resample over fit threshold
      if not self.imbalanced and EVAL_SET_INDEX in self.data.columns:
          sample_threshold = self.FIT_SAMPLE_WITH_EVAL_SET_THRESHOLD
          sample_rows = self.FIT_SAMPLE_WITH_EVAL_SET_ROWS
      else:
          sample_threshold = self.FIT_SAMPLE_THRESHOLD
          sample_rows = self.FIT_SAMPLE_ROWS
  
      if len(self.data) > sample_threshold:
          self.logger.info(
              f"Etalon has size {len(self.data)} more than threshold {sample_threshold} "
              f"and will be downsampled to {sample_rows}"
          )
          resampled_data = self.data.sample(
              n=sample_rows, random_state=self.random_state
          )
          self.data = resampled_data
          self.logger.info(
              f"Shape after threshold resampling: {self.data.shape}"
          )
  
imports: import csv
  import hashlib
  import logging
  import tempfile
  import time
  from ipaddress import IPv4Address, IPv6Address, _BaseAddress, ip_address
  from pathlib import Path
  from typing import Any, Callable, Dict, List, Optional, Tuple, Union
  import numpy
  import pandas
  from pandas.api.types import is_bool_dtype
  from pandas.api.types import is_datetime64_any_dtype
  from pandas.api.types import is_float_dtype, is_integer_dtype, is_numeric_dtype, is_string_dtype
  from pandas.core.dtypes.common import is_period_dtype
  from upgini.errors import ValidationError
  from upgini.http import ProgressStage, SearchProgress, get_rest_client
  from upgini.metadata import EVAL_SET_INDEX, SYSTEM_COLUMNS, SYSTEM_RECORD_ID, TARGET, DataType, FeaturesFilter, FileColumnMeaningType, FileColumnMetadata, FileMetadata, FileMetrics, ModelTaskType, NumericInterval, RuntimeParameters, SearchCustomization
  from upgini.normalizer.phone_normalizer import PhoneNormalizer
  from upgini.resource_bundle import bundle
  from upgini.sampler.random_under_sampler import RandomUnderSampler
  from upgini.search_task import SearchTask
  from upgini.utils import combine_search_keys
  from upgini.utils.email_utils import EmailSearchKeyConverter
  from upgini.utils.warning_counter import WarningCounter
label_desc: Use image node_id 28 for calling the Dataset obj's underlying member method code with example usage: obj.__resample() without return types