docs: def _get_attribute_info(self):
          """ Preprocess the training dataset to identify which features/attributes are discrete vs. continuous valued. Ignores missing values in this determination."""
          attr = dict()
          d = 0
          limit = self.discrete_threshold
          w = self._X.transpose()
  
          for idx in range(len(w)):
              h = self._headers[idx]
              z = w[idx]
              if self._missing_data_count > 0:
                  z = z[np.logical_not(np.isnan(z))]  # Exclude any missing values from consideration
              zlen = len(np.unique(z))
              if zlen <= limit:
                  attr[h] = ('discrete', 0, 0, 0, 0)
                  d += 1
              else:
                  mx = np.max(z)
                  mn = np.min(z)
                  sd = np.std(z)
                  attr[h] = ('continuous', mx, mn, mx - mn, sd)
          # For each feature/attribute we store (type, max value, min value, max min difference, average, standard deviation) - the latter three values are set to zero if feature is discrete.
          return attr