code: def metrics_as_dataframes(
      metrics: Iterable[MetricsForSlice],
      *,  # Keyword only args below.
      include_empty_columns: bool = False,
  ) -> MetricsDataFrames:
      """Convert the deserialized MetricsForSlice protos to Pandas DataFrame.
  
      To load all metrics:
        dfs = metrics_as_dataframe(tfma.load_metrics(output_path))
      then users can load "double_value" DataFrame as
        dfs.double_value
      and confusion_metrics_at_thresholds DataFrame as:
        dfs.confusion_metrics_at_thresholds:
  
      For example, if the input metrics proto looks like this:
            slice_key {
               single_slice_keys {
                 column: "age"
                 float_value: 38.0
               }
             }
             metric_keys_and_values {
               key {
                 name: "mean_absolute_error"
               }
               value {
                 double_value {
                   value: 0.1
                 }
               }
             }
             metric_keys_and_values {
               key {
                 name: "mean_squared_logarithmic_error"
               }
               value {
                 double_value {
                   value: 0.02
                 }
               }
             }
  
      The corresponding output table will look like this:
  
      |    | metric_values| metric_keys                    |               slices |
      |    | double_value |           name                 |       age |      sex |
      |---:|-------------:|:-------------------------------|----------:|:---------|
      |  0 |         0.1  | mean_absolute_error            |        38 | male     |
      |  1 |         0.02 | mean_squared_logarithmic_error |        38 | female   |
  
      One typical use of this DataFrame table is to re-organize it in the form of
      slices vs. metrics table. For single model single output:
        `auto_pivot(dfs.double_value)`
      This will pivot on the non-unique "metric_keys.*" columns.
  
      Args:
        metrics: The directory path of the metrics file or an iterable of
          MetricsForSlice proto.
        include_empty_columns: Include a column if its value is not empty (None) in
          corresponding field in the MetricKey.
  
      Returns:
        A DataFrame with the following columns if the value is not None:
        * slices.<slice_feature_column>: feature columns derived from
          tfma.proto.metrics_for_slice_pb2.SliceKey. There are multiple feature
          columns if there is any feature-cross, e.g., slice.featureA and
          slice.featureB if there is FeatureA and FeatureB cross.
        * metric_keys.<metric_key_column>: recursively flattened items in
          metric_key: name, model_name, output_name, is_diff, example_weighted,
          flattened sub_key (class_id, k, top_k), flattened aggregation_type
          (micro_average, macro_average, weighted_macro_average).
        * metric_values.<metric_value_columns>: column(s) of metric_value(s);
          metric_value specified by metric_type and flattened to its leaf
          primitives. E.g.,
            'double_value' if metric_type is 'double_value';
            'true_positives', 'false_negatives', etc. if metric_type is
              'confusion_matrix_at_thresholds'.
      """
      dfs = _to_dataframes(
          metrics,
          column_prefixes=_metric_columns,
          include_empty_columns=include_empty_columns,
      )
      return MetricsDataFrames(**dfs)
  
imports: import collections
  import dataclasses
  import itertools
  from typing import Any, Dict, Iterable, Iterator, List, Optional, Tuple, Union
  import numpy
  import pandas
  from tensorflow_model_analysis.proto import metrics_for_slice_pb2
  from google.protobuf import wrappers_pb2
  from google.protobuf import descriptor
  from google.protobuf import message
label_desc: Use image node_id 4 for calling a global function with example usage: metrics_as_dataframes(metrics) and returns: MetricsDataFrames