class_docstr_tok: []
docstr: :param original_df: a dataframe containing a required raw 'score' column
      and possible raw 'label_value' column.
  :param disparity_df: Expansion of get_crosstabs() output with additional
      columns for disparity metrics and each metric's reference group to
      which significance must be added
  :param ref_dict: Dictionary indicating reference group for each
      attribute/ measure combination
  :param score_thresholds: a dictionary {'rank_abs':[], 'rank_pct':[], 'score':[]}
  :param model_id: (Future functionality) ID(s) of models for which to check
      statistical significance
  :param attr_cols: Columns indicating attribute values in original_df
  :param alpha: Level at which to determine statistical significance.
      Default is 5e-2 (0.05).
  
  :return: dataframe with same number of rows as the input (crosstab)
      but with additional disparity metrics columns, ref_group_values, and
      statistical significance (p-values) of specific metrics.
docstr_tok: [":","param","original_df",":","a","dataframe","containing","a","required","raw","'score","'","column","and","possible","raw","'label_value","'","column",".",":","param","disparity_df",":","Expansion","of","get_crosstabs","(",")","output","with","additional","columns","for","disparity","metrics","and","each","metric","'s","reference","group","to","which","significance","must","be","added",":","param","ref_dict",":","Dictionary","indicating","reference","group","for","each","attribute\/","measure","combination",":","param","score_thresholds",":","a","dictionary","{","'rank_abs","'",":","[","]",",","'rank_pct","'",":","[","]",",","'score","'",":","[","]","}",":","param","model_id",":","(","Future","functionality",")","ID","(","s",")","of","models","for","which","to","check","statistical","significance",":","param","attr_cols",":","Columns","indicating","attribute","values","in","original_df",":","param","alpha",":","Level","at","which","to","determine","statistical","significance",".","Default","is","5e-2","(","0.05",")",".",":","return",":","dataframe","with","same","number","of","rows","as","the","input","(","crosstab",")","but","with","additional","disparity","metrics","columns",",","ref_group_values",",","and","statistical","significance","(","p-values",")","of","specific","metrics","."]
code: def _get_statistical_significance(
      cls,
      original_df,
      disparity_df,
      ref_dict,
      score_thresholds=None,
      attr_cols=None,
      alpha=5e-2,
      selected_significance=False,
  ):
      """
  
      :param original_df: a dataframe containing a required raw 'score' column
          and possible raw 'label_value' column.
      :param disparity_df: Expansion of get_crosstabs() output with additional
          columns for disparity metrics and each metric's reference group to
          which significance must be added
      :param ref_dict: Dictionary indicating reference group for each
          attribute/ measure combination
      :param score_thresholds: a dictionary {'rank_abs':[], 'rank_pct':[], 'score':[]}
      :param model_id: (Future functionality) ID(s) of models for which to check
          statistical significance
      :param attr_cols: Columns indicating attribute values in original_df
      :param alpha: Level at which to determine statistical significance.
          Default is 5e-2 (0.05).
  
      :return: dataframe with same number of rows as the input (crosstab)
          but with additional disparity metrics columns, ref_group_values, and
          statistical significance (p-values) of specific metrics.
      """
      if "label_value" not in original_df.columns:
          raise ValueError(
              "Column 'label_value' not in dataframe. Label values are "
              "required for computing statistical significance of supervised "
              "metrics."
          )
  
      if attr_cols is None:
          non_attr_cols = [
              "id",
              "model_id",
              "entity_id",
              "score",
              "label_value",
              "rank_abs",
              "rank_pct",
          ]
  
          # index of the columns that are attributes
          attr_cols = original_df.columns[
              ~original_df.columns.isin(non_attr_cols)
          ]
  
      # check if all attr_cols exist in df
      if set(attr_cols) - set(original_df.columns):
          raise ValueError(
              f"Not all attribute columns provided '{attr_cols}' exist in "
              f"input dataframe."
          )
  
      # check if all columns are strings:
      non_string_cols = original_df.columns[
          (original_df.dtypes != object)
          & (original_df.dtypes != str)
          & (original_df.columns.isin(attr_cols))
      ]
  
      binary_inclusions = {
          f"binary_{col}"
          for col in (selected_significance or cls.significance_cols)
          if col != "label_value"
      }
  
      # check whether necessary binary columns already created
      if not non_string_cols.empty:
          # check whether error message is required based on if only binary columns
          if not all("binary_" in col for col in non_string_cols):
              raise ValueError(
                  "get_statistical_significance: statistical significance was "
                  "not calculated. There are non-string cols within attr_cols."
              )
  
          # skip binary column creation if all necessary columns already created
          elif not binary_inclusions - set(non_string_cols):
              measures = set(
                  original_df.columns[
                      original_df.columns.str.contains("binary_")
                  ]
              )
              measures = measures.union({"label_value"})
  
              for attribute in set(attr_cols) - measures:
                  for measure in measures:
                      # only calculate significance if in selected_significance
                      if (measure in selected_significance) or (
                          measure.replace("binary_", "")
                          in selected_significance
                      ):
                          cls._calculate_significance(
                              original_df,
                              disparity_df,
                              attribute,
                              measure,
                              ref_dict=ref_dict,
                              alpha=alpha,
                          )
  
              return disparity_df
  
          else:
              # drop old binary columns and generate those in binary_inclusions
              # as though non_string_cols was empty
              drop_cols = list(
                  original_df.columns[
                      original_df.columns.str.contains("binary_")
                  ]
              )
              drop_cols += list(
                  original_df.columns[
                      original_df.columns.str.contains("rank_")
                  ]
              )
              original_df = original_df.drop(drop_cols, axis=1)
  
      # create binary columns if non_string_cols is empty or binaries dropped
  
      # if no score_thresholds are provided, we assume that rank_abs equals
      # the number  of 1s in the score column; it also serves as flag to set
      # parameter to 'binary'
      count_ones = None
      if not score_thresholds:
          original_df.loc[:, "score"] = original_df.loc[
              :, "score"
          ].astype(float)
  
          count_ones = original_df["score"].value_counts().get(1.0, 0)
          score_thresholds = {"rank_abs": [count_ones]}
  
      original_df.sort_values("score", ascending=False, inplace=True)
      original_df.loc[:, "rank_abs"] = range(1, len(original_df) + 1)
      original_df.loc[:, "rank_pct"] = original_df.loc[
          :, "rank_abs"
      ] / len(original_df)
  
      # Define formula for binary false positive, false negative, binary score
      binary_false_pos = lambda rank_col, label_col, thres: lambda x: (
          (x[rank_col] <= thres) & (x[label_col] == 0)
      ).astype(int)
  
      binary_false_neg = lambda rank_col, label_col, thres: lambda x: (
          (x[rank_col] > thres) & (x[label_col] == 1)
      ).astype(int)
  
      binary_score = lambda rank_col, label_col, thres: lambda x: (
          x[rank_col] <= thres
      ).astype(int)
  
      binary_col_functions = {
          "binary_score": binary_score,
          "binary_fpr": binary_false_pos,
          "binary_fnr": binary_false_neg,
      }
  
      for thres_unit, thres_values in score_thresholds.items():
          for thres_val in thres_values:
              for name, func in binary_col_functions.items():
                  func = func(thres_unit, "label_value", thres_val)
                  original_df.loc[:, name] = original_df.apply(
                      func, axis=1
                  )
  
      # add columns for error-based significance
      # precision, tnr, fdr are based on false positives
      SIGNIF_BASES = {
          "binary_precision": "binary_fpr",
          "binary_tnr": "binary_fpr",
          "binary_fdr": "binary_fpr",
          "binary_npv": "binary_fnr",
          "binary_tpr": "binary_fnr",
          "binary_for": "binary_fnr",
          "binary_ppr": "binary_score",
          "binary_pprev": "binary_score",
      }
  
      # add columns for the rest of columns in dictionary keys
      # binary score, fnr, fpr already added above
      for col in binary_inclusions - binary_col_functions.keys():
          original_df.loc[:, col] = original_df.loc[
              :, SIGNIF_BASES[col]
          ]
  
      # ensure only predicted positive values included in true positive
      # error based metrics, and only predicted negative values in false
      # positive error based metrics
      POSITIVE_ONLY = [
          "binary_fpr",
          "binary_tnr",
          "binary_precision",
          "binary_fdr",
      ]
      NEGATIVE_ONLY = [
          "binary_fnr",
          "binary_tpr",
          "binary_npv",
          "binary_for",
      ]
  
      FPR_BASED = [
          metric
          for metric in POSITIVE_ONLY
          if metric in binary_inclusions
      ]
      FNR_BASED = [
          metric
          for metric in NEGATIVE_ONLY
          if metric in binary_inclusions
      ]
  
      original_df.loc[
          original_df["binary_score"] == 0, FPR_BASED
      ] = np.nan
      original_df.loc[
          original_df["binary_score"] == 1, FNR_BASED
      ] = np.nan
  
      measures = set(
          original_df.columns[
              original_df.columns.str.contains("binary_")
          ]
      )
      measures = measures.union({"label_value"})
  
      for attribute in attr_cols:
          for measure in measures:
              # only calculate significance if in selected_significance
              if (measure in selected_significance) or (
                  measure.replace("binary_", "")
                  in selected_significance
              ):
                  cls._calculate_significance(
                      original_df,
                      disparity_df,
                      attribute,
                      measure,
                      ref_dict=ref_dict,
                      alpha=alpha,
                  )
      return disparity_df
  
file_path: aequitas/src/aequitas/bias.py
imports: import logging
  from aequitas.plotting import assemble_ref_groups
  import numpy
  import pandas
  from scipy import stats
label_desc: Use image node_id 10 for calling the Bias obj's underlying member method code with example usage: obj._get_statistical_significance(cls, original_df, disparity_df, ref_dict, score_thresholds, attr_cols, alpha, selected_significance) and returns: disparity_df, disparity_df