code: def permutation_evaluator(
      test_data: pd.DataFrame,
      predict_fn: PredictFnType,
      eval_fn: EvalFnType,
      baseline: bool = True,
      features: List[str] = None,
      shuffle_all_at_once: bool = False,
      random_state: int = None,
  ) -> EvalReturnType:
      """
      Permutation importance evaluator.
      It works by shuffling one or more features on test_data dataframe,
      getting the preditions with predict_fn, and evaluating the results with eval_fn.
  
      Parameters
      ----------
      test_data : Pandas' DataFrame
          A Pandas' DataFrame with target, predictions and features.
  
      predict_fn : function DataFrame -> DataFrame
          Function that receives the input dataframe and returns a dataframe with the pipeline predictions.
  
      eval_fn : function DataFrame -> Log Dict
          A partially applied evaluation function.
  
      baseline: bool
          Also evaluates the predict_fn on an unshuffled baseline.
  
      features : List of strings
          The features to shuffle and then evaluate eval_fn on the shuffled results.
          The default case shuffles all dataframe columns.
  
      shuffle_all_at_once: bool
          Shuffle all features at once instead of one per turn.
  
      random_state: int
          Seed to be used by the random number generator.
  
      eval_name : String, optional (default=None)
          the name of the evaluator as it will appear in the logs.
  
      Returns
      -------
      log: dict
          A log-like dictionary with evaluation results by feature shuffle.
          Use the permutation_extractor for better visualization of the results.
      """
  
      if features is None:
          features = list(test_data.columns)
  
      def col_shuffler(f: str) -> np.ndarray:
          return (
              test_data[f]
              .sample(frac=1.0, random_state=random_state)
              .values
          )
  
      def permutation_eval(
          features_to_shuffle: List[str],
      ) -> EvalReturnType:
          shuffled_cols = {
              f: col_shuffler(f) for f in features_to_shuffle
          }
          return eval_fn(predict_fn(test_data.assign(**shuffled_cols)))
  
      if shuffle_all_at_once:
          permutation_results = {
              "-".join(features): permutation_eval(features)
          }
      else:
          permutation_results = {
              f: permutation_eval([f]) for f in features
          }
  
      feature_importance = {
          "permutation_importance": permutation_results
      }
  
      if baseline:
          baseline_results = {
              "permutation_importance_baseline": eval_fn(
                  predict_fn(test_data)
              )
          }
      else:
          baseline_results = {}
  
      return fp.merge(feature_importance, baseline_results)
  
imports: import warnings
  from typing import Any, Callable, Iterable, List
  import numpy
  import pandas
  import toolz
  from pandas.util import hash_pandas_object
  from sklearn.metrics import average_precision_score, brier_score_loss, fbeta_score, log_loss, mean_absolute_error, mean_squared_error, precision_score, r2_score, recall_score, roc_auc_score
  from toolz import curry, last, first
  from scipy import optimize
  from sklearn.linear_model import LogisticRegression
  from fklearn.types import EvalFnType, EvalReturnType, PredictFnType, UncurriedEvalFnType
label_desc: Use image node_id 21 for calling a global function with example usage: permutation_evaluator(test_data, predict_fn, eval_fn, baseline, features, shuffle_all_at_once, random_state) and returns: fp, test_data, eval_fn