code: def _best_split(self, X, y):
      n = y.size
      if n <= 1:
          return None, None, 0
  
      orig_impurity = self._gini(y)
      impurity_reduction = 0
      best_impurity_reduction = 0
      best_idx, best_thr = None, None
  
      # loop over features
      for idx in range(self.n_features):
          thresholds, y_classes = zip(*sorted(zip(X[:, idx], y)))
          y_classes = np.array(y_classes)
  
          # consider every point where threshold value changes
          idx_thresholds = (
              1 + np.where(np.diff(thresholds))[0]
          ).tolist()
          for i in idx_thresholds:
              # calculate impurity for left and right
              y_left = y_classes[:i]
              y_right = y_classes[i:]
              impurity_reduction = (
                  orig_impurity
                  - (
                      y_left.size * self._gini(y_left)
                      + y_right.size * self._gini(y_right)
                  )
                  / n
              )
  
              if self.impurity_func == "information_gain_ratio":
                  split_info = -(
                      y_left.size / n * np.log2(y_left.size / n)
                  ) - (y_right.size / n * np.log2(y_right.size / n))
                  if ~np.isnan(split_info):
                      impurity_reduction = (
                          impurity_reduction / split_info
                      )
              if self.impurity_func == "cost_information_gain_ratio":
                  impurity_reduction /= self.feature_costs_[idx]
  
              if impurity_reduction > best_impurity_reduction:
                  best_impurity_reduction = impurity_reduction
                  best_idx = idx
                  best_thr = (thresholds[i] + thresholds[i - 1]) / 2
  
      return best_idx, best_thr, impurity_reduction
  
imports: from sklearn.tree._tree import Tree
  from sklearn.tree import DecisionTreeClassifier, DecisionTreeRegressor
  from sklearn.base import ClassifierMixin, RegressorMixin
  from sklearn import __version__
  from collections import namedtuple
  import pandas
  import numpy
  from collections import namedtuple
  from sklearn import __version__
  from sklearn.base import ClassifierMixin, RegressorMixin
  from sklearn.tree import DecisionTreeClassifier, DecisionTreeRegressor
  from sklearn.tree._tree import Tree
  import imodels.util.tree
label_desc: Use image node_id 4 for calling the CustomDecisionTreeClassifier obj's underlying member method code with example usage: obj._best_split(X, y) and returns: best_idx,  best_thr,  impurity_reduction, None,  None,  int