class_docstr: Creates a xp result plot out of the given dataframe: regret with respect to budget for
  each optimizer after averaging on all experiments (it is good practice to use a df
  which is filtered out for one set of input parameters)
  
  Parameters
  ----------
  optim_vals: dict
      output of the make_data static method, containing all information necessary for plotting
  title: str
      title of the plot
  name_style: dict
      a dict or dict-like object providing a line style for each optimizer name.
      (can be helpful for consistency across plots)
docstr: Process raw xp data and process it to extract relevant information for xp plots:
  regret with respect to budget for each optimizer after averaging on all experiments (it is good practice to use a df
  which is filtered out for one set of input parameters)
  
  Parameters
  ----------
  df: pd.DataFrame
      run data
  normalized_loss: bool
      whether we should normalize each data (for each budget and run) between 0 and 1. Convenient when we consider
      averages over several distinct functions that can have very different ranges - then we return data which are rescaled to [0,1].
      Warning: then even if algorithms converge (i.e. tend to minimize), the value can increase, because the normalization
      is done separately for each budget.
docstr_tok: ["Process","raw","xp","data","and","process","it","to","extract","relevant","information","for","xp","plots",":","regret","with","respect","to","budget","for","each","optimizer","after","averaging","on","all","experiments","(","it","is","good","practice","to","use","a","df","which","is","filtered","out","for","one","set","of","input","parameters",")","Parameters","--","--","--","--","--","df",":","pd.DataFrame","run","data","normalized_loss",":","bool","whether","we","should","normalize","each","data","(","for","each","budget","and","run",")","between","0","and","1",".","Convenient","when","we","consider","averages","over","several","distinct","functions","that","can","have","very","different","ranges","-","then","we","return","data","which","are","rescaled","to","[","0,1","]",".","Warning",":","then","even","if","algorithms","converge","(","i.e",".","tend","to","minimize",")",",","the","value","can","increase",",","because","the","normalization","is","done","separately","for","each","budget","."]
code: def make_data(
      df: pd.DataFrame, normalized_loss: bool = False
  ) -> tp.Dict[str, tp.Dict[str, np.ndarray]]:
      """Process raw xp data and process it to extract relevant information for xp plots:
      regret with respect to budget for each optimizer after averaging on all experiments (it is good practice to use a df
      which is filtered out for one set of input parameters)
  
      Parameters
      ----------
      df: pd.DataFrame
          run data
      normalized_loss: bool
          whether we should normalize each data (for each budget and run) between 0 and 1. Convenient when we consider
          averages over several distinct functions that can have very different ranges - then we return data which are rescaled to [0,1].
          Warning: then even if algorithms converge (i.e. tend to minimize), the value can increase, because the normalization
          is done separately for each budget.
      """
      if normalized_loss:
          descriptors = sorted(
              set(df.columns)
              - {
                  "pseudotime",
                  "time",
                  "budget",
                  "elapsed_time",
                  "elapsed_budget",
                  "loss",
                  "optimizer_name",
                  "seed",
              }
          )
          df = normalized_losses(df, descriptors=descriptors)
      df = utils.Selector(
          df.loc[
              :,
              ["optimizer_name", "budget", "loss"]
              + (["pseudotime"] if "pseudotime" in df.columns else []),
          ]
      )
      groupeddf = df.groupby(["optimizer_name", "budget"])
      means = groupeddf.mean()
      stds = groupeddf.std()
      optim_vals: tp.Dict[str, tp.Dict[str, np.ndarray]] = {}
      # extract name and coordinates
      for optim in df.unique("optimizer_name"):
          optim_vals[optim] = {}
          optim_vals[optim]["budget"] = np.array(
              means.loc[optim, :].index
          )
          optim_vals[optim]["loss"] = np.array(means.loc[optim, "loss"])
          optim_vals[optim]["loss_std"] = np.array(
              stds.loc[optim, "loss"]
          )
          num_eval = np.array(groupeddf.count().loc[optim, "loss"])
          optim_vals[optim]["num_eval"] = num_eval
          if "pseudotime" in means.columns:
              optim_vals[optim]["pseudotime"] = np.array(
                  means.loc[optim, "pseudotime"]
              )
      return optim_vals
  
imports: import os
  import re
  import string
  import hashlib
  import warnings
  import argparse
  import itertools
  from collections import defaultdict
  from pathlib import Path
  import numpy
  import pandas
  from matplotlib import pyplot
  from matplotlib.legend import Legend
  from matplotlib import cm
  from mpl_toolkits.axes_grid1 import make_axes_locatable
  import nevergrad.common.typing
  from .None import utils
  from .exporttable import export_table
label_desc: Use image node_id 4 for calling the XpPlotter obj's underlying member method code with example usage: obj.make_data(df, normalized_loss) and returns: optim_vals