code: def agg_batch(dir, metric_best="auto"):
      r"""
      Aggregate across results from multiple experiments via grid search
  
      Args:
          dir (str): Directory of the results, containing multiple experiments
          metric_best (str, optional): The metric for selecting the best
          validation performance. Options: auto, accuracy, auc.
  
      """
      import pandas as pd
  
      results = {"train": [], "val": [], "test": []}
      for run in os.listdir(dir):
          if run != "agg":
              dict_name = name_to_dict(run)
              dir_run = os.path.join(dir, run, "agg")
              if os.path.isdir(dir_run):
                  for split in os.listdir(dir_run):
                      dir_split = os.path.join(dir_run, split)
                      fname_stats = os.path.join(dir_split, "best.json")
                      dict_stats = json_to_dict_list(fname_stats)[
                          -1
                      ]  # get best val epoch
                      rm_keys(
                          dict_stats,
                          [
                              "lr",
                              "lr_std",
                              "eta",
                              "eta_std",
                              "params_std",
                          ],
                      )
                      results[split].append({**dict_name, **dict_stats})
      dir_out = os.path.join(dir, "agg")
      makedirs_rm_exist(dir_out)
      for key in results:
          if len(results[key]) > 0:
              results[key] = pd.DataFrame(results[key])
              results[key] = results[key].sort_values(
                  list(dict_name.keys()),
                  ascending=[True] * len(dict_name),
              )
              fname = os.path.join(dir_out, "{}_best.csv".format(key))
              results[key].to_csv(fname, index=False)
  
      results = {"train": [], "val": [], "test": []}
      for run in os.listdir(dir):
          if run != "agg":
              dict_name = name_to_dict(run)
              dir_run = os.path.join(dir, run, "agg")
              if os.path.isdir(dir_run):
                  for split in os.listdir(dir_run):
                      dir_split = os.path.join(dir_run, split)
                      fname_stats = os.path.join(
                          dir_split, "stats.json"
                      )
                      dict_stats = json_to_dict_list(fname_stats)[
                          -1
                      ]  # get last epoch
                      rm_keys(
                          dict_stats,
                          [
                              "lr",
                              "lr_std",
                              "eta",
                              "eta_std",
                              "params_std",
                          ],
                      )
                      results[split].append({**dict_name, **dict_stats})
      dir_out = os.path.join(dir, "agg")
      for key in results:
          if len(results[key]) > 0:
              results[key] = pd.DataFrame(results[key])
              results[key] = results[key].sort_values(
                  list(dict_name.keys()),
                  ascending=[True] * len(dict_name),
              )
              fname = os.path.join(dir_out, "{}.csv".format(key))
              results[key].to_csv(fname, index=False)
  
      results = {"train": [], "val": [], "test": []}
      for run in os.listdir(dir):
          if run != "agg":
              dict_name = name_to_dict(run)
              dir_run = os.path.join(dir, run, "agg")
              if os.path.isdir(dir_run):
                  for split in os.listdir(dir_run):
                      dir_split = os.path.join(dir_run, split)
                      fname_stats = os.path.join(
                          dir_split, "stats.json"
                      )
                      dict_stats = json_to_dict_list(
                          fname_stats
                      )  # get best epoch
                      if metric_best == "auto":
                          metric = (
                              "auc"
                              if "auc" in dict_stats[0]
                              else "accuracy"
                          )
                      else:
                          metric = metric_best
                      performance_np = np.array(  # noqa
                          [stats[metric] for stats in dict_stats]
                      )
                      dict_stats = dict_stats[
                          eval(
                              "performance_np.{}()".format(
                                  cfg.metric_agg
                              )
                          )
                      ]
                      rm_keys(
                          dict_stats,
                          [
                              "lr",
                              "lr_std",
                              "eta",
                              "eta_std",
                              "params_std",
                          ],
                      )
                      results[split].append({**dict_name, **dict_stats})
      dir_out = os.path.join(dir, "agg")
      for key in results:
          if len(results[key]) > 0:
              results[key] = pd.DataFrame(results[key])
              results[key] = results[key].sort_values(
                  list(dict_name.keys()),
                  ascending=[True] * len(dict_name),
              )
              fname = os.path.join(
                  dir_out, "{}_bestepoch.csv".format(key)
              )
              results[key].to_csv(fname, index=False)
  
      print(
          "Results aggregated across models saved in {}".format(dir_out)
      )
  
file_path: GraphGym/graphgym/utils/agg_runs.py
imports: import logging
  import os
  import numpy
  from graphgym.config import cfg
  from graphgym.utils.io import dict_list_to_json, dict_list_to_tb, dict_to_json, json_to_dict_list, makedirs_rm_exist, string_to_python
label_desc: Use image node_id 8 for calling a global function with example usage: agg_batch(dir, metric_best) without return types