class_docstr: A sampler that uses an underlying training set to draw records that have a subset of features with
  values specified in an instance to be explained, `X`. 
class_docstr_tok: ["A","sampler","that","uses","an","underlying","training","set","to","draw","records","that","have","a","subset","of","features","with","values","specified","in","an","instance","to","be","explained",",","`","X","`","."]
docstr: An encoding of the feature IDs is created by assigning each bin of a discretized numerical variable and each
  categorical variable a unique index. For a dataset containing, e.g., a numerical variable with 5 bins and
  3 categorical variables, indices 0 - 4 represent bins of the numerical variable whereas indices 5, 6, 7
  represent the encoded indices of the categorical variables (but see note for caviats). The encoding is
  necessary so that the different ranges of the numerical variable can be sampled during result construction.
  Note that the encoded indices represent the predicates used during the anchor construction process (i.e., and
  anchor is a collection of encoded indices.
  
  Parameters
  ---------
  X
      Instance to be explained.
  
  Returns
  -------
  A list containing three dictionaries, whose keys are encoded feature IDs
  
   - `cat_lookup` - maps categorical variables to their value in `X`.
  
   - `ord_lookup` - maps discretized numerical variables to the bins they can be sampled from given `X`.
  
   - `enc2feat_idx` - maps the encoded IDs to the original (training set) feature column IDs.
  
  Notes
  -----
  Each continuous variable has `n_bins - 1` corresponding entries in `ord_lookup`.
code: def build_lookups(self, X: np.ndarray) -> List[Dict]:
      """
      An encoding of the feature IDs is created by assigning each bin of a discretized numerical variable and each
      categorical variable a unique index. For a dataset containing, e.g., a numerical variable with 5 bins and
      3 categorical variables, indices 0 - 4 represent bins of the numerical variable whereas indices 5, 6, 7
      represent the encoded indices of the categorical variables (but see note for caviats). The encoding is
      necessary so that the different ranges of the numerical variable can be sampled during result construction.
      Note that the encoded indices represent the predicates used during the anchor construction process (i.e., and
      anchor is a collection of encoded indices.
  
      Parameters
      ---------
      X
          Instance to be explained.
  
      Returns
      -------
      A list containing three dictionaries, whose keys are encoded feature IDs
  
       - `cat_lookup` - maps categorical variables to their value in `X`.
  
       - `ord_lookup` - maps discretized numerical variables to the bins they can be sampled from given `X`.
  
       - `enc2feat_idx` - maps the encoded IDs to the original (training set) feature column IDs.
  
      Notes
      -----
      Each continuous variable has `n_bins - 1` corresponding entries in `ord_lookup`.
      """
  
      X = self.disc.discretize(X.reshape(1, -1))[
          0
      ]  # map continuous features to ordinal discrete variables
  
      if (
          not self.numerical_features
      ):  # data contains only categorical variables
          self.cat_lookup = dict(zip(self.categorical_features, X))
          self.enc2feat_idx = dict(
              zip(*[self.categorical_features] * 2)
          )
          return [self.cat_lookup, self.ord_lookup, self.enc2feat_idx]
  
      first_numerical_idx = np.searchsorted(
          self.categorical_features, self.numerical_features[0]
      ).item()
      if (
          first_numerical_idx > 0
      ):  # First column(s) might contain categorical data
          for cat_enc_idx in range(0, first_numerical_idx):
              self.cat_lookup[cat_enc_idx] = X[cat_enc_idx]
              self.enc2feat_idx[cat_enc_idx] = cat_enc_idx
  
      ord_enc_idx = (
          first_numerical_idx - 1
      )  # -1 as increment comes first
      for i, feature in enumerate(self.numerical_features):
          n_bins = len(self.feature_values[feature])
          for bin_val in range(n_bins):
              ord_enc_idx += 1
              self.enc2feat_idx[ord_enc_idx] = feature
              # if feat. value falls in same or lower bin, sample from same or lower bin only ...
              if X[feature] <= bin_val != n_bins - 1:
                  self.ord_lookup[ord_enc_idx] = set(
                      i for i in range(bin_val + 1)
                  )
              # if feat. value falls in a higher bin, sample from higher bins only
              elif X[feature] > bin_val:
                  self.ord_lookup[ord_enc_idx] = set(
                      i for i in range(bin_val + 1, n_bins)
                  )
              else:
                  del self.enc2feat_idx[ord_enc_idx]
                  ord_enc_idx -= 1  # when a discretized feat. of the instance to be explained falls in the last bin
  
          # check if a categorical feature follows the current numerical feature & update mappings
          if i < len(self.numerical_features) - 1:
              n_categoricals = (
                  self.numerical_features[i + 1]
                  - self.numerical_features[i]
                  - 1
              )
              if n_categoricals > 0:
                  cat_feat_idx = feature + 1
                  for cat_enc_idx in range(
                      ord_enc_idx + 1, ord_enc_idx + 1 + n_categoricals
                  ):
                      self.cat_lookup[cat_enc_idx] = X[cat_feat_idx]
                      self.enc2feat_idx[cat_enc_idx] = cat_feat_idx
                      cat_feat_idx += 1
                  ord_enc_idx += n_categoricals
  
      # check if the last columns are categorical variables and update mappings
      last_num_idx = np.searchsorted(
          self.categorical_features, self.numerical_features[-1]
      ).item()
      if last_num_idx != len(self.categorical_features):
          cat_enc_idx = max(self.ord_lookup.keys()) + 1
          for cat_feat_idx in range(
              self.numerical_features[-1] + 1,
              self.categorical_features[-1] + 1,
          ):
              self.cat_lookup[cat_enc_idx] = X[cat_feat_idx]
              self.enc2feat_idx[cat_enc_idx] = cat_feat_idx
              cat_enc_idx += 1
  
      return [self.cat_lookup, self.ord_lookup, self.enc2feat_idx]
  
imports: import copy
  from collections import OrderedDict, defaultdict
  from itertools import accumulate
  from typing import Any, Callable, DefaultDict, Dict, List, Optional, Set, Tuple, Type, Union
  import numpy
  from alibi.api.defaults import DEFAULT_DATA_ANCHOR, DEFAULT_META_ANCHOR
  from alibi.api.interfaces import Explainer, Explanation, FitMixin
  from alibi.exceptions import NotFittedError, PredictorCallError, PredictorReturnTypeError
  from alibi.utils.discretizer import Discretizer
  from alibi.utils.mapping import ohe_to_ord, ord_to_ohe
  from alibi.utils.wrappers import ArgmaxTransformer
  from .anchor_base import AnchorBaseBeam
  from .anchor_explanation import AnchorExplanation
label_desc: Use image node_id 15 for calling the TabularSampler obj's underlying member method code with example usage: obj.build_lookups(X) and returns: list, list