code: def _build_profiles_and_card(
      self, train_df, validation_df, test_df
  ) -> BaseCard:
      from sklearn.utils import compute_class_weight
  
      def _set_target_col_as_first(df, target_col):
          columns = list(df.columns)
          col = columns.pop(columns.index(target_col))
          return df[[col] + columns]
  
      # Build card
      card = BaseCard(self.recipe_name, self.name)
  
      if not self.skip_data_profiling:
          # Build profiles for input dataset, and train / validation / test splits
          train_df = _set_target_col_as_first(train_df, self.target_col)
          validation_df = _set_target_col_as_first(
              validation_df, self.target_col
          )
          test_df = _set_target_col_as_first(test_df, self.target_col)
          data_profile = get_pandas_data_profiles(
              [
                  ["Train", train_df.reset_index(drop=True)],
                  ["Validation", validation_df.reset_index(drop=True)],
                  ["Test", test_df.reset_index(drop=True)],
              ]
          )
  
          # Tab #1 - #3: data profiles for train/validation and test.
          card.add_tab(
              "Compare Splits", "{{PROFILE}}"
          ).add_pandas_profile("PROFILE", data_profile)
  
          if self.task == "classification":
              if self.positive_class is not None:
                  mask = (
                      train_df[self.target_col] == self.positive_class
                  )
                  dfs_for_profiles = [
                      ("Positive", train_df[mask]),
                      ("Negative", train_df[~mask]),
                  ]
                  sub_title = "Positive vs Negative"
              else:
                  classes = np.unique(train_df[self.target_col])
                  class_weights = compute_class_weight(
                      class_weight="balanced",
                      classes=classes,
                      y=train_df[self.target_col],
                  )
                  class_weights = list(zip(classes, class_weights))
                  class_weights = sorted(
                      class_weights, key=lambda x: x[1], reverse=True
                  )
                  if len(class_weights) > _MAX_CLASSES_TO_PROFILE:
                      class_weights = class_weights[
                          :_MAX_CLASSES_TO_PROFILE
                      ]
                  dfs_for_profiles = [
                      (
                          name,
                          train_df[(train_df[self.target_col] == name)],
                      )
                      for name, _ in class_weights
                  ]
                  sub_title = (
                      f"Top {min(5, len(class_weights))} Classes"
                  )
  
              profiles = [
                  [
                      str(p[0]),
                      p[1]
                      .drop(columns=[self.target_col])
                      .reset_index(drop=True),
                  ]
                  for p in dfs_for_profiles
              ]
              generated_profile = get_pandas_data_profiles(profiles)
              # Tab #4: data profiles positive negative training split.
              card.add_tab(
                  f"Compare Training Data ({sub_title})", "{{PROFILE}}"
              ).add_pandas_profile("PROFILE", generated_profile)
  
      # Tab #5: run summary.
      (
          card.add_tab(
              "Run Summary",
              """
                  {{ SCHEMA_LOCATION }}
                  {{ TRAIN_SPLIT_NUM_ROWS }}
                  {{ VALIDATION_SPLIT_NUM_ROWS }}
                  {{ TEST_SPLIT_NUM_ROWS }}
                  {{ NUM_DROPPED_ROWS }}
                  {{ EXE_DURATION}}
                  {{ LAST_UPDATE_TIME }}
                  """,
          )
          .add_markdown(
              "NUM_DROPPED_ROWS",
              f"**Number of dropped rows:** `{self.num_dropped_rows}`",
          )
          .add_markdown(
              "TRAIN_SPLIT_NUM_ROWS",
              f"**Number of train dataset rows:** `{len(train_df)}`",
          )
          .add_markdown(
              "VALIDATION_SPLIT_NUM_ROWS",
              f"**Number of validation dataset rows:** `{len(validation_df)}`",
          )
          .add_markdown(
              "TEST_SPLIT_NUM_ROWS",
              f"**Number of test dataset rows:** `{len(test_df)}`",
          )
      )
  
      return card
  
imports: import importlib
  import logging
  import os
  import sys
  import time
  from enum import Enum
  from functools import partial
  from multiprocessing.pool import Pool, ThreadPool
  import numpy
  import pandas
  from mlflow.exceptions import BAD_REQUEST, INVALID_PARAMETER_VALUE, MlflowException
  from mlflow.recipes.artifacts import DataframeArtifact
  from mlflow.recipes.cards import BaseCard
  from mlflow.recipes.step import BaseStep, StepClass
  from mlflow.recipes.utils.execution import get_step_output_path
  from mlflow.recipes.utils.step import get_pandas_data_profiles, validate_classification_config
  from mlflow.store.artifact.artifact_repo import _NUM_DEFAULT_CPUS
  from mlflow.utils.time import Timer
label_desc: Use image node_id 2 for calling the SplitStep obj's underlying member method code with example usage: obj._build_profiles_and_card(train_df, validation_df, test_df) and returns: card, df