class_docstr: Abstract class - Build a class that inherits from this class to implement
  a custom discretizer.
  Method bins() is to be redefined in the child class, as it is the actual
  custom part of the discretizer.
class_docstr_tok: ["Abstract","class","-","Build","a","class","that","inherits","from","this","class","to","implement","a","custom","discretizer",".","Method","bins","(",")","is","to","be","redefined","in","the","child","class",",","as","it","is","the","actual","custom","part","of","the","discretizer","."]
docstr: Initializer
  Args:
      data: numpy 2d array
      categorical_features: list of indices (ints) corresponding to the
          categorical columns. These features will not be discretized.
          Everything else will be considered continuous, and will be
          discretized.
      categorical_names: map from int to list of names, where
          categorical_names[x][y] represents the name of the yth value of
          column x.
      feature_names: list of names (strings) corresponding to the columns
          in the training data.
      data_stats: must have 'means', 'stds', 'mins' and 'maxs', use this
          if you don't want these values to be computed from data
docstr_tok: ["Initializer","Args",":","data",":","numpy","2d","array","categorical_features",":","list","of","indices","(","ints",")","corresponding","to","the","categorical","columns",".","These","features","will","not","be","discretized",".","Everything","else","will","be","considered","continuous",",","and","will","be","discretized",".","categorical_names",":","map","from","int","to","list","of","names",",","where","categorical_names","[","x","]","[","y","]","represents","the","name","of","the","yth","value","of","column","x.","feature_names",":","list","of","names","(","strings",")","corresponding","to","the","columns","in","the","training","data",".","data_stats",":","must","have","'means","'",",","'stds","'",",","'mins","'","and","'maxs","'",",","use","this","if","you","do","n't","want","these","values","to","be","computed","from","data"]
code: def __init__(
      self,
      data,
      categorical_features,
      feature_names,
      labels=None,
      random_state=None,
      data_stats=None,
  ):
      """Initializer
      Args:
          data: numpy 2d array
          categorical_features: list of indices (ints) corresponding to the
              categorical columns. These features will not be discretized.
              Everything else will be considered continuous, and will be
              discretized.
          categorical_names: map from int to list of names, where
              categorical_names[x][y] represents the name of the yth value of
              column x.
          feature_names: list of names (strings) corresponding to the columns
              in the training data.
          data_stats: must have 'means', 'stds', 'mins' and 'maxs', use this
              if you don't want these values to be computed from data
      """
      self.to_discretize = [
          x
          for x in range(data.shape[1])
          if x not in categorical_features
      ]
      self.data_stats = data_stats
      self.names = {}
      self.lambdas = {}
      self.means = {}
      self.stds = {}
      self.mins = {}
      self.maxs = {}
      self.random_state = check_random_state(random_state)
  
      # To override when implementing a custom binning
      bins = self.bins(data, labels)
      bins = [np.unique(x) for x in bins]
  
      # Read the stats from data_stats if exists
      if data_stats:
          self.means = self.data_stats.get("means")
          self.stds = self.data_stats.get("stds")
          self.mins = self.data_stats.get("mins")
          self.maxs = self.data_stats.get("maxs")
  
      for feature, qts in zip(self.to_discretize, bins):
          n_bins = qts.shape[
              0
          ]  # Actually number of borders (= #bins-1)
          boundaries = np.min(data[:, feature]), np.max(
              data[:, feature]
          )
          name = feature_names[feature]
  
          self.names[feature] = ["%s <= %.2f" % (name, qts[0])]
          for i in range(n_bins - 1):
              self.names[feature].append(
                  "%.2f < %s <= %.2f" % (qts[i], name, qts[i + 1])
              )
          self.names[feature].append(
              "%s > %.2f" % (name, qts[n_bins - 1])
          )
  
          self.lambdas[feature] = lambda x, qts=qts: np.searchsorted(
              qts, x
          )
          discretized = self.lambdas[feature](data[:, feature])
  
          # If data stats are provided no need to compute the below set of details
          if data_stats:
              continue
  
          self.means[feature] = []
          self.stds[feature] = []
          for x in range(n_bins + 1):
              selection = data[discretized == x, feature]
              mean = 0 if len(selection) == 0 else np.mean(selection)
              self.means[feature].append(mean)
              std = 0 if len(selection) == 0 else np.std(selection)
              std += 0.00000000001
              self.stds[feature].append(std)
          self.mins[feature] = [boundaries[0]] + qts.tolist()
          self.maxs[feature] = qts.tolist() + [boundaries[1]]
  
imports: import numpy
  import sklearn
  import sklearn.tree
  import scipy
  from sklearn.utils import check_random_state
  from abc import ABCMeta, abstractmethod
label_desc: Use image node_id 1 to create a new BaseDiscretizer object  with example: obj = BaseDiscretizer(data, categorical_features, feature_names, labels, random_state, data_stats)