code: def plot_permutation_importance(
      exp: Explanation,
      features: Union[List[int], Literal["all"]] = "all",
      metric_names: Union[
          List[Union[str, int]], Literal["all"]
      ] = "all",
      n_cols: int = 3,
      sort: bool = True,
      top_k: Optional[int] = None,
      ax: Optional[Union["plt.Axes", np.ndarray]] = None,
      bar_kw: Optional[dict] = None,
      fig_kw: Optional[dict] = None,
  ) -> "plt.Axes":
      """
      Plot permutation feature importance on `matplotlib` axes.
  
      Parameters
      ----------
      exp
          An `Explanation` object produced by a call to the
          :py:meth:`alibi.explainers.permutation_importance.PermutationImportance.explain` method.
      features
          A list of feature entries provided in `feature_names` argument  to the
          :py:meth:`alibi.explainers.permutation_importance.PermutationImportance.explain` method, or
          ``'all'`` to  plot all the explained features. For example, consider that the
          ``feature_names = ['temp', 'hum', 'windspeed', 'season']``. If we set `features=None` in the `explain` method,
          meaning that all the feature were explained, and we want to plot only the values  for the ``'temp'`` and
          ``'windspeed'``, then we would set ``features=[0, 2]``. Otherwise, if we set `features=[1, 2, 3]` in the
          explain method, meaning that we explained ``['hum', 'windspeed', 'season']``, and we want to plot the values
          only for ``['windspeed', 'season']``, then we would set ``features=[1, 2]`` (i.e., their index in the
          `features` list passed to the `explain` method). Defaults to ``'all'``.
      metric_names
          A list of metric entries in the `exp.data['metrics']` to plot the permutation feature importance for,
          or ``'all'`` to plot the permutation feature importance for all metrics (i.e., loss and score functions).
          The ordering is given by the concatenation of the loss metrics followed by the score metrics.
      n_cols
          Number of columns to organize the resulting plot into.
      sort
          Boolean flag whether to sort the values in descending order.
      top_k
          Number of top k values to be displayed if the ``sort=True``. If not provided, then all values will be displayed.
      ax
          A `matplotlib` axes object or a `numpy` array of `matplotlib` axes to plot on.
      bar_kw
          Keyword arguments passed to the `matplotlib.pyplot.barh`_ function.
      fig_kw
          Keyword arguments passed to the `matplotlib.figure.set`_ function.
  
          .. _matplotlib.pyplot.barh:
              https://matplotlib.org/stable/api/_as_gen/matplotlib.pyplot.barh.html
  
          .. _matplotlib.figure.set:
              https://matplotlib.org/stable/api/figure_api.html
  
      Returns
      --------
      `plt.Axes` with the feature importance plot.
      """
      from matplotlib.gridspec import GridSpec
  
      # define figure arguments
      default_fig_kw = {"tight_layout": "tight"}
      if fig_kw is None:
          fig_kw = {}
  
      fig_kw = {**default_fig_kw, **fig_kw}
  
      if features == "all":
          features = list(range(len(exp.data["feature_names"])))
  
      metric_names = deepcopy(
          exp.data["metric_names"]
          if metric_names == "all"
          else metric_names
      )
  
      # `features` sanity checks
      for ifeature in features:
          if ifeature >= len(exp.data["feature_names"]):
              raise IndexError(
                  f"The `features` indices must be less than the "
                  f"``len(feature_names) = {len(exp.data['feature_names'])}``. Received {ifeature}."
              )
  
      # construct vector of feature names to display importance for
      feature_names = [exp.data["feature_names"][i] for i in features]
  
      # `metric_names` sanity checks
      for i, imetric_name in enumerate(metric_names):
          if isinstance(imetric_name, str) and (
              imetric_name not in exp.data["metric_names"]
          ):
              raise ValueError(
                  f"Unknown metric name. Received {imetric_name}. "
                  f"Available values are: {exp.data['metric_names']}."
              )
  
          if isinstance(imetric_name, numbers.Integral):
              if imetric_name >= len(exp.data["metric_names"]):
                  raise IndexError(
                      f"Metric name index out of range. Received {imetric_name}. "
                      f"The number of `metric_names` is {len(exp.data['metric_names'])}"
                  )
  
              # convert index to string
              metric_names[i] = exp.data["metric_names"][imetric_name]
  
      if ax is None:
          fix, ax = plt.subplots()
  
      # number of metrics will correspond to the number of axis
      n_metric_names = len(metric_names)
  
      if isinstance(ax, plt.Axes) and n_metric_names != 1:
          ax.set_axis_off()  # treat passed axis as a canvas for subplots
          fig = ax.figure
          n_cols = min(n_cols, n_metric_names)
          n_rows = math.ceil(n_metric_names / n_cols)
  
          axes = np.empty((n_rows, n_cols), dtype=object)
          axes_ravel = axes.ravel()
          gs = GridSpec(n_rows, n_cols)
  
          for i, spec in zip(range(n_metric_names), gs):
              axes_ravel[i] = fig.add_subplot(spec)
  
      else:  # array-like
          if isinstance(ax, plt.Axes):
              ax = np.array(ax)
  
          if ax.size < n_metric_names:
              raise ValueError(
                  f"Expected ax to have {n_metric_names} axes, got {ax.size}"
              )
  
          axes = np.atleast_2d(ax)
          axes_ravel = axes.ravel()
          fig = axes_ravel[0].figure
  
      for i in range(n_metric_names):
          ax = axes_ravel[i]
          metric_idx = exp.data["metric_names"].index(metric_names[i])
  
          # define bar plot data
          y_labels = feature_names
          y_labels = [
              "(" + ", ".join(y_label) + ")"
              if isinstance(y_label, tuple)
              else y_label
              for y_label in y_labels
          ]
  
          if exp.meta["params"]["method"] == Method.EXACT:
              width = [
                  exp.data["feature_importance"][metric_idx][j]
                  for j in features
              ]
              xerr = None
          else:
              width = [
                  exp.data["feature_importance"][metric_idx][j]["mean"]
                  for j in features
              ]
              xerr = [
                  exp.data["feature_importance"][metric_idx][j]["std"]
                  for j in features
              ]
  
          if sort:
              sorted_indices = np.argsort(width)[::-1][:top_k]
              width = [width[j] for j in sorted_indices]
              y_labels = [y_labels[j] for j in sorted_indices]
  
              if exp.meta["params"]["method"] == Method.ESTIMATE:
                  xerr = [xerr[j] for j in sorted_indices]
  
          y = np.arange(len(width))
          default_bar_kw = {"align": "center"}
          bar_kw = (
              default_bar_kw
              if bar_kw is None
              else {**default_bar_kw, **bar_kw}
          )
  
          ax.barh(y=y, width=width, xerr=xerr, **bar_kw)
          ax.set_yticks(y)
          ax.set_yticklabels(y_labels)
          ax.invert_yaxis()  # labels read top-to-bottom
          ax.set_xlabel("Permutation feature importance")
          ax.set_title(metric_names[i])
  
      fig.set(**fig_kw)
      return axes
  
imports: import copy
  import inspect
  import logging
  import math
  import numbers
  import sys
  from collections import defaultdict
  from copy import deepcopy
  from enum import Enum
  from typing import Any, Callable, Dict, List, Optional, Tuple, Union, no_type_check
  import matplotlib.pyplot
  import numpy
  import sklearn.metrics
  from tqdm import tqdm
  from alibi.api.defaults import DEFAULT_DATA_PERMUTATION_IMPORTANCE, DEFAULT_META_PERMUTATION_IMPORTANCE
  from alibi.api.interfaces import Explainer, Explanation
label_desc: Use image node_id 1 for calling a global function with example usage: plot_permutation_importance(exp, features, metric_names, n_cols, sort, top_k, ax, bar_kw, fig_kw) and returns: axes