class_docstr: Calculates absolute metrics for a given dataframe with model scores and
  labels, divided by different values on protected attributes.
  
  Attributes
  ----------
  absolute_metrics : List[str]
      Calculated bias metrics.
  
  Methods
  -------
  get_crosstabs(df, score_thresholds=None, attr_cols=None, score_col="score", label_col="label_value")
      Calculates metrics for a given dataframe.
  get_multimodel_crosstabs(df, score_thresholds=None, attr_cols=None, score_col="score", label_col="label_value")
      Calculates metrics for a given dataframe with multiple models.
class_docstr_tok: ["Calculates","absolute","metrics","for","a","given","dataframe","with","model","scores","and","labels",",","divided","by","different","values","on","protected","attributes",".","Attributes","--","--","--","--","--","absolute_metrics",":","List","[","str","]","Calculated","bias","metrics",".","Methods","--","--","--","-","get_crosstabs","(","df",",","score_thresholds=None",",","attr_cols=None",",","score_col=","''","score","''",",","label_col=","''","label_value","''",")","Calculates","metrics","for","a","given","dataframe",".","get_multimodel_crosstabs","(","df",",","score_thresholds=None",",","attr_cols=None",",","score_col=","''","score","''",",","label_col=","''","label_value","''",")","Calculates","metrics","for","a","given","dataframe","with","multiple","models","."]
docstr: Calculates metrics for a given dataframe.
  
  Generates the confusion matrix given the scores in the `score` column
  and the "label_value" for each unique value in each of the `attr_cols`.
  Then, the metrics that are derived from the confusion matrix are
  calculated.
  
  To add a different metric, add the name of the metric in the `columns`
  variable and calculate it in the inner for cycle.
  
  Parameters
  ----------
  df : pandas.DataFrame
      Classification, label and protected attributes on a given dataset.
      The classification column must already be binary, and in
      column `score`. The label column must be in the column
      "label_value".
  attr_cols : List[str]
      Columns of the dataframe that represent protected attributes.
  score : str
      Column of the dataframe that represents classification result.
      Values in the column must be binary.
  label : str
      Column of the dataframe that represents label of instance.
      Values in the column must be binary.
  score_threshold : str
      Type of threshold used to binarize score.
  Returns
  -------
  pandas.DataFrame
      Metrics for each group in the protected attribute.
docstr_tok: ["Calculates","metrics","for","a","given","dataframe",".","Generates","the","confusion","matrix","given","the","scores","in","the","`","score","`","column","and","the","``","label_value","''","for","each","unique","value","in","each","of","the","`","attr_cols","`",".","Then",",","the","metrics","that","are","derived","from","the","confusion","matrix","are","calculated",".","To","add","a","different","metric",",","add","the","name","of","the","metric","in","the","`","columns","`","variable","and","calculate","it","in","the","inner","for","cycle",".","Parameters","--","--","--","--","--","df",":","pandas.DataFrame","Classification",",","label","and","protected","attributes","on","a","given","dataset",".","The","classification","column","must","already","be","binary",",","and","in","column","`","score","`",".","The","label","column","must","be","in","the","column","``","label_value","''",".","attr_cols",":","List","[","str","]","Columns","of","the","dataframe","that","represent","protected","attributes",".","score",":","str","Column","of","the","dataframe","that","represents","classification","result",".","Values","in","the","column","must","be","binary",".","label",":","str","Column","of","the","dataframe","that","represents","label","of","instance",".","Values","in","the","column","must","be","binary",".","score_threshold",":","str","Type","of","threshold","used","to","binarize","score",".","Returns","--","--","--","-","pandas.DataFrame","Metrics","for","each","group","in","the","protected","attribute","."]
code: def gen_metrics_df(
      df: pd.DataFrame,
      attr_cols: List[str],
      score: str,
      label: str,
      score_threshold: str,
  ) -> pd.DataFrame:
      """
      Calculates metrics for a given dataframe.
  
      Generates the confusion matrix given the scores in the `score` column
      and the "label_value" for each unique value in each of the `attr_cols`.
      Then, the metrics that are derived from the confusion matrix are
      calculated.
  
      To add a different metric, add the name of the metric in the `columns`
      variable and calculate it in the inner for cycle.
  
      Parameters
      ----------
      df : pandas.DataFrame
          Classification, label and protected attributes on a given dataset.
          The classification column must already be binary, and in
          column `score`. The label column must be in the column
          "label_value".
      attr_cols : List[str]
          Columns of the dataframe that represent protected attributes.
      score : str
          Column of the dataframe that represents classification result.
          Values in the column must be binary.
      label : str
          Column of the dataframe that represents label of instance.
          Values in the column must be binary.
      score_threshold : str
          Type of threshold used to binarize score.
      Returns
      -------
      pandas.DataFrame
          Metrics for each group in the protected attribute.
      """
      # Method to handle divisions by 0.
      divide = lambda x, y: x / y if y != 0 else np.nan
      model_id = Group._check_model_id(df, "df")
      columns = [  # Columns in the resulting dataframe
          "model_id",
          "score_threshold",
          "k",
          "attribute_name",
          "attribute_value",
          "accuracy",
          "tpr",
          "tnr",
          "fomr",
          "fdr",
          "fpr",
          "fnr",
          "npv",
          "precision",
          "pp",
          "pn",
          "ppr",
          "pprev",
          "fp",
          "fn",
          "tn",
          "tp",
          "group_label_pos",
          "group_label_neg",
          "group_size",
          "total_entities",
          "prev",
      ]
      final_dict = {column: [] for column in columns}
      # k = Total number of predicted positives in sample.
      # This is for pd.DataFrames only.
      k = df[df[score] == 1].shape[0]
      for attribute_name in attr_cols:
          # Create confusion matrix for each group in the form of dictionary.
          # This is for pd.DataFrames only.
          grouped_data = (
              df.groupby(by=[attribute_name, score, label])
              .size()
              .to_dict(into=OrderedDict)
          )
          # Select the possible (unique) values of the protected attributes (groups).
          # list(OrderedDict.fromkeys()) works like an ordered set.
          attribute_values = list(
              OrderedDict.fromkeys([key[0] for key in grouped_data])
          )
  
          for attribute_value in attribute_values:
              # Get confusion matrix from the dictionary.
              tp = grouped_data.get((attribute_value, 1, 1), 0)
              tn = grouped_data.get((attribute_value, 0, 0), 0)
              fp = grouped_data.get((attribute_value, 1, 0), 0)
              fn = grouped_data.get((attribute_value, 0, 1), 0)
              # Calculate all metrics from confusion matrix.
              accuracy = divide(tp + tn, tp + tn + fp + fn)
              tpr = divide(tp, fn + tp)
              tnr = divide(tn, fp + tn)
              # We can't have variables named 'for', this is changed in return
              fomr = divide(fn, fn + tn)
              fdr = divide(fp, tp + fp)
              fpr = divide(fp, fp + tn)
              fnr = divide(fn, fn + tp)
              npv = divide(tn, fn + tn)
              precision = divide(tp, tp + fp)
              pp = fp + tp
              pn = fn + tn
              ppr = divide(pp, k)
              pprev = divide(pp, pp + pn)
              group_label_pos = fn + tp
              group_label_neg = fp + tn
              group_size = group_label_pos + group_label_neg
              total_entities = df.shape[0]
              prev = (fn + tp) / group_size
              for key in final_dict.keys():
                  # Maybe using locals is not the best, but it is the least
                  # messy solution in terms of code.
                  final_dict[key].append(locals()[key])
      # Rename column fomr -> for (impossible to have variable named for).
      return pd.DataFrame(final_dict).rename(columns={"fomr": "for"})
  
file_path: aequitas/src/aequitas/group.py
imports: import logging
  import uuid
  from typing import Any, Dict, List, Tuple, Union
  from collections import OrderedDict
  import numpy
  import pandas
  from .bias import Bias
  from .plot import summary, disparity, absolute
label_desc: Use image node_id 2 for calling the Group obj's underlying member method code with example usage: obj.gen_metrics_df(df, attr_cols, score, label, score_threshold) and returns: pd