class_docstr: Computes predictive differences and their uncertainty intervals for
  'comparisons' and 'slopes' effects and returns a summary dataframe of the
  results.
  
  Parameters
  ----------
  model : Model
      Bambi model object.
  preds_data : pd.DataFrame
      Dataframe used to generate predictions.
  variable : VariableInfo
      Variable of interest with its name and values.
  conditional : ConditionalInfo
      Conditional covariates with their names and values (if any).
  response : ResponseInfo
      Response variable with its name and target.
  use_hdi : bool
      Whether to use the highest density interval (HDI) (True) or quantiles (False).
  kind : str
      Type of effect to compute. Either 'comparisons' or 'slopes'.
  
  Returns
  -------
  summary_df : pd.DataFrame
      Dataframe with the data used to generate predictions, the effect kind
      and type, variable of interest name and value, and the mean and uncertainty
      intervals of the predictive difference estimate.
docstr: Builds the summary dataframe for 'comparisons' and 'slopes' effects.
  There are four scenarios to consider:
  
      1.) If the effect kind is 'comparisons' and more than 2 values are being
      compared, then the entire 'preds' data is used.
  
      2.) If the model predictions have multiple response levels, then 'preds' data
      needs to be duplicated to match the number of response levels. E.g., 'preds'
      data has 100 rows and 3 response levels, then the summary dataframe will have
      300 rows since the model made a prediction for each response level for each
      sample in 'preds'.
  
      3.) If the effect kind is 'slopes' and more than 2 values are being compared, then
      only a subset of the 'preds' data is used to build the summary.
  
      4.) If the number of values passed for the variable of interest is less then 2
      for 'comparisons' and 'slopes', then a subset of the 'preds' data is used
      to build the summary.
docstr_tok: ["Builds","the","summary","dataframe","for","'comparisons","'","and","'slopes","'","effects",".","There","are","four","scenarios","to","consider",":","1",".",")","If","the","effect","kind","is","'comparisons","'","and","more","than","2","values","are","being","compared",",","then","the","entire","'preds","'","data","is","used",".","2",".",")","If","the","model","predictions","have","multiple","response","levels",",","then","'preds","'","data","needs","to","be","duplicated","to","match","the","number","of","response","levels",".","E.g.",",","'preds'","data","has","100","rows","and","3","response","levels",",","then","the","summary","dataframe","will","have","300","rows","since","the","model","made","a","prediction","for","each","response","level","for","each","sample","in","'preds","'",".","3",".",")","If","the","effect","kind","is","'slopes","'","and","more","than","2","values","are","being","compared",",","then","only","a","subset","of","the","'preds","'","data","is","used","to","build","the","summary",".","4",".",")","If","the","number","of","values","passed","for","the","variable","of","interest","is","less","then","2","for","'comparisons","'","and","'slopes","'",",","then","a","subset","of","the","'preds","'","data","is","used","to","build","the","summary","."]
code: def get_summary_df(self, response_dim: np.ndarray) -> pd.DataFrame:
      """
      Builds the summary dataframe for 'comparisons' and 'slopes' effects.
      There are four scenarios to consider:
  
          1.) If the effect kind is 'comparisons' and more than 2 values are being
          compared, then the entire 'preds' data is used.
  
          2.) If the model predictions have multiple response levels, then 'preds' data
          needs to be duplicated to match the number of response levels. E.g., 'preds'
          data has 100 rows and 3 response levels, then the summary dataframe will have
          300 rows since the model made a prediction for each response level for each
          sample in 'preds'.
  
          3.) If the effect kind is 'slopes' and more than 2 values are being compared, then
          only a subset of the 'preds' data is used to build the summary.
  
          4.) If the number of values passed for the variable of interest is less then 2
          for 'comparisons' and 'slopes', then a subset of the 'preds' data is used
          to build the summary.
      """
      # scenario 1
      if len(self.variable.values) > 2 and self.kind == "comparisons":
          summary_df = self.preds_data.drop(
              columns=self.variable.name
          ).drop_duplicates()
          covariates_cols = summary_df.columns
          contrast_values = list(
              itertools.combinations(self.variable.values.flatten(), 2)
          )
          covariate_vals = np.tile(summary_df.T, len(contrast_values))
          summary_df = pd.DataFrame(
              data=covariate_vals.T, columns=covariates_cols
          )
          contrast_values = np.repeat(
              contrast_values,
              summary_df.shape[0] // len(contrast_values),
              axis=0,
          )
          contrast_values = [tuple(elem) for elem in contrast_values]
      # scenario 2
      elif len(response_dim) > 1:
          summary_df = self.preds_data.drop(
              columns=self.variable.name
          ).drop_duplicates()
          covariates_cols = summary_df.columns
          contrast_values = self.variable.values.flatten()
          covariate_vals = np.repeat(summary_df.T, len(response_dim))
          summary_df = pd.DataFrame(
              data=covariate_vals.T, columns=covariates_cols
          )
          summary_df["estimate_dim"] = np.tile(
              response_dim, summary_df.shape[0] // len(response_dim)
          )
          contrast_values = [tuple(contrast_values)] * summary_df.shape[
              0
          ]
      # scenario 3 & 4
      else:
          wrt = {}
          for idx, _ in enumerate(self.variable.values):
              mask = np.array(
                  self.preds_data[self.variable.name].isin(
                      self.variable.values[idx]
                  )
              )
              wrt[f"draw_mask_{idx}"] = self.preds_data[mask][
                  self.variable.name
              ].reset_index(drop=True)
              # only need to get "a" dataframe since remaining N dataframes are identical
              if idx == 0:
                  summary_df = (
                      self.preds_data[mask]
                      .drop(columns=self.variable.name)
                      .reset_index(drop=True)
                  )
          contrast_values = pd.concat(wrt.values(), axis=1).apply(
              tuple, axis=1
          )
  
      summary_df.insert(0, "term", self.variable.name)
      summary_df.insert(1, "estimate_type", self.estimate_name)
      summary_df.insert(2, "value", contrast_values)
      summary_df.insert(
          len(summary_df.columns), "estimate", self.estimate.mean
      )
      summary_df.insert(
          len(summary_df.columns),
          self.response.lower_bound_name,
          self.estimate.lower,
      )
      summary_df.insert(
          len(summary_df.columns),
          self.response.upper_bound_name,
          self.estimate.higher,
      )
  
      self.summary_df = summary_df
      self.contrast_values = contrast_values
  
      return self.summary_df
  
imports: from dataclasses import dataclass, field
  import itertools
  from typing import Dict, Union
  import arviz
  import numpy
  import pandas
  from pandas.api.types import is_categorical_dtype, is_string_dtype
  import xarray
  from bambi.models import Model
  from bambi.interpret.create_data import create_differences_data, create_predictions_data
  from bambi.interpret.utils import average_over, ConditionalInfo, enforce_dtypes, identity, merge, VariableInfo
  from bambi.utils import get_aliased_name
label_desc: Use image node_id 4 for calling the PredictiveDifferences obj's underlying member method code with example usage: obj.get_summary_df(response_dim) and returns: self