code: def permutation_importances(
      model,
      X,
      y,
      metric,
      onehot_dict=None,
      greater_is_better=True,
      needs_proba=False,
      pos_label=1,
      n_repeats=1,
      n_jobs=None,
      sort=True,
      pass_nparray=False,
      verbose=0,
  ):
      """
      adapted from rfpimp package, returns permutation importances, optionally grouping
      onehot-encoded features together.
  
      Args:
          model: fitted model for which you'd like to calculate importances.
          X (pd.DataFrame): dataframe of features
          y (pd.Series): series of targets
          metric: metric to be evaluated (usually R2 for regression, roc_auc for
              classification)
          onehot_dict (dict): dict of features with lists for onehot-encoded variables,
               e.g. {'Fare': ['Fare'], 'Sex' : ['Sex_male', 'Sex_Female']}
          greater_is_better (bool): indicates whether the higher score on the metric
              indicates a better model.
          needs_proba (bool): does the metric need a classification probability
              or direct prediction?
          pos_label (int): for classification, the label to use a positive label.
              Defaults to 1.
          n_repeats (int): number of time to permute each column to take the average score.
              Defaults to 1.
          n_jobs (int): number of jobs for joblib parallel. Defaults to None.
          sort (bool): sort the output from highest importances to lowest.
          pass_nparray (bool, optional): instead of the X pass X.values to model.
              This is useful for skorch models that do not accepts dataframes.
          verbose (int): set to 1 to print output for debugging. Defaults to 0.
      """
      X = X.copy()
  
      if onehot_dict is None:
          onehot_dict = {col: [col] for col in X.columns}
  
      if isinstance(metric, str):
          scorer = make_scorer(
              metric,
              greater_is_better=greater_is_better,
              needs_proba=needs_proba,
          )
      elif not needs_proba or pos_label is None:
          scorer = make_scorer(
              metric,
              greater_is_better=greater_is_better,
              needs_proba=needs_proba,
          )
      else:
          scorer = make_one_vs_all_scorer(
              metric, pos_label, greater_is_better
          )
      if pass_nparray:
          baseline = scorer(model, X.values, y.values)
      else:
          baseline = scorer(model, X, y)
  
      def _permutation_importance(
          model,
          X,
          y,
          scorer,
          col_name,
          col_list,
          baseline,
          n_repeats=1,
          pass_nparray=False,
      ):
          X = X.copy()
          scores = []
          for i in range(n_repeats):
              old_cols = X[col_list].copy()
              X[col_list] = np.random.permutation(X[col_list])
              if pass_nparray:
                  scores.append(scorer(model, X.values, y.values))
              else:
                  scores.append(scorer(model, X, y))
  
              X[col_list] = old_cols
          return col_name, np.mean(scores)
  
      scores = Parallel(n_jobs=n_jobs)(
          delayed(_permutation_importance)(
              model,
              X,
              y,
              scorer,
              col_name,
              col_list,
              baseline,
              n_repeats,
              pass_nparray,
          )
          for col_name, col_list in onehot_dict.items()
      )
  
      importances_df = pd.DataFrame(
          scores, columns=["Feature", "Score"]
      )
      importances_df["Importance"] = baseline - importances_df["Score"]
      importances_df = importances_df[
          ["Feature", "Importance", "Score"]
      ]
      if sort:
          return importances_df.sort_values(
              "Importance", ascending=False
          )
      else:
          return importances_df
  
imports: from functools import partial
  import re
  from collections import Counter
  from typing import List, Union
  import warnings
  import numpy
  import pandas
  from pandas.api.types import is_numeric_dtype, is_categorical_dtype
  from dtreeviz.trees import ShadowDecTree
  from sklearn.metrics import make_scorer
  from sklearn.base import clone
  from sklearn.pipeline import Pipeline
  from sklearn.model_selection import KFold, StratifiedKFold
  from joblib import Parallel, delayed
label_desc: Use image node_id 17 for calling a global function with example usage: permutation_importances(model, X, y, metric, onehot_dict, greater_is_better, needs_proba, pos_label, n_repeats, n_jobs, sort, pass_nparray, verbose) and returns: col_name,  np, importances_df, importances_df