code: def loss_after_permutation(
      data, y, model, predict, loss_function, variables, N, rng
  ):
      if isinstance(N, int):
          N = min(N, data.shape[0])
          sampled_rows = rng.choice(
              np.arange(data.shape[0]), N, replace=False
          )
          sampled_data = data.iloc[sampled_rows, :]
          observed = y[sampled_rows]
      else:
          sampled_data = data
          observed = y
  
      # loss on the full model or when outcomes are permuted
      loss_full = loss_function(observed, predict(model, sampled_data))
  
      sampled_rows2 = rng.choice(
          range(observed.shape[0]), observed.shape[0], replace=False
      )
      loss_baseline = loss_function(
          observed[sampled_rows2], predict(model, sampled_data)
      )
  
      loss_features = {}
      for variables_set_key in variables:
          ndf = sampled_data.copy()
          ndf.loc[:, variables[variables_set_key]] = (
              ndf.iloc[
                  rng.choice(range(ndf.shape[0]), ndf.shape[0], False),
                  :,
              ]
              .loc[:, variables[variables_set_key]]
              .values
          )
  
          predicted = predict(model, ndf)
  
          loss_features[variables_set_key] = loss_function(
              observed, predicted
          )
  
      loss_features["_full_model_"] = loss_full
      loss_features["_baseline_"] = loss_baseline
  
      return pd.DataFrame(loss_features, index=[0])
  
imports: import multiprocessing
  from numpy.random import SeedSequence, default_rng
  import numpy
  import pandas
label_desc: Use image node_id 2 for calling a global function with example usage: loss_after_permutation(data, y, model, predict, loss_function, variables, N, rng) and returns: pd