code: def _plot_two_pd_cat_cat(
      exp: Explanation,
      feature: int,
      target_idx: int,
      ax: Optional["plt.Axes"] = None,
      pd_cat_cat_kw: Optional[dict] = None,
  ) -> Tuple["plt.Axes", Optional[Tuple[float, float]]]:
      """
      Plots two ways partial dependence curve for two categorical features.
  
      Parameters
      ----------
      exp, feature, pd_cat_cat_kw
          See :py:meth:`alibi.explainers.partial_dependence.plot_pd` method.
      target_idx
          The target index for which to plot the partial dependence (PD) curves. An integer
          denoting target index in `exp.meta['params']['target_names']`.
      ax
          Pre-existing axes for the plot. Otherwise, call `matplotlib.pyplot.gca()` internally.
  
      Return
      ------
      `matplotlib` axes and ``None``.
      """
      import matplotlib.pyplot as plt
  
      from alibi.utils.visualization import heatmap
  
      if ax is None:
          ax = plt.gca()
  
      if exp.meta["params"]["kind"] not in [Kind.AVERAGE, Kind.BOTH]:
          raise ValueError(
              "Can only plot partial dependence for `kind` in `['average', 'both']`."
          )
  
      feature_names = exp.data["feature_names"][feature]
      feature_values = exp.data["feature_values"][feature]
      pd_values = exp.data["pd_values"][feature][target_idx]
  
      # extract labels for each categorical features
      feature0_index = exp.meta["params"]["feature_names"].index(
          feature_names[0]
      )
      feature1_index = exp.meta["params"]["feature_names"].index(
          feature_names[1]
      )
      labels0 = [
          exp.meta["params"]["categorical_names"][feature0_index][i]
          for i in feature_values[0].astype(np.int32)
      ]
      labels1 = [
          exp.meta["params"]["categorical_names"][feature1_index][i]
          for i in feature_values[1].astype(np.int32)
      ]
  
      # plot heatmap
      default_pd_cat_cat_kw = {
          "annot": True,
          "fmt": "{x:.2f}",
          "linewidths": 1.5,
          "yticklabels": labels0,
          "xticklabels": labels1,
          "aspect": "auto",
      }
      pd_cat_cat_kw = (
          default_pd_cat_cat_kw
          if pd_cat_cat_kw is None
          else {**default_pd_cat_cat_kw, **pd_cat_cat_kw}
      )
      heatmap(pd_values, ax=ax, **pd_cat_cat_kw)
  
      # set ticks labels
      ax.set_xticklabels(labels1)
      ax.set_yticklabels(labels0)
  
      # set axis labels
      ax.set_xlabel(exp.data["feature_names"][feature][1])
      ax.set_ylabel(exp.data["feature_names"][feature][0])
      return ax, None
  
imports: import copy
  import logging
  import math
  import numbers
  import sys
  from abc import ABC, abstractmethod
  from enum import Enum
  from typing import Callable, Dict, Iterable, List, Optional, Tuple, Union, no_type_check
  import matplotlib.pyplot
  import numpy
  from scipy.stats.mstats import mquantiles
  from sklearn.base import BaseEstimator, is_classifier, is_regressor
  from sklearn.ensemble import RandomForestRegressor
  from sklearn.ensemble._gb import BaseGradientBoosting
  from sklearn.ensemble._hist_gradient_boosting.gradient_boosting import BaseHistGradientBoosting
  from sklearn.tree import DecisionTreeRegressor
  from sklearn.utils.extmath import cartesian
  from sklearn.utils.validation import check_is_fitted
  from tqdm import tqdm
  from alibi.api.defaults import DEFAULT_DATA_PD, DEFAULT_META_PD
  from alibi.api.interfaces import Explainer, Explanation
  from alibi.explainers.ale import get_quantiles
  from alibi.utils import _get_options_string
label_desc: Use image node_id 8 for calling a global function with example usage: _plot_two_pd_cat_cat(exp, feature, target_idx, ax, pd_cat_cat_kw) and returns: ax,  None