class_docstr: Class storing mapping-like results for an experiment.
  
  Data is stored in a dataframe, and auxiliary information ((key name,
  default value) pairs) are stored in a collection of MapKeyInfo objects.
  
  Mapping-like results occur whenever a metric is reported as a collection
  of results, each element corresponding to a tuple of values.
  
  The simplest case is a sequence. For instance a time series is
  a mapping from the 1-tuple `(timestamp)` to (mean, sem) results.
  
  Another example: MultiFidelity results. This is a mapping from
  `(fidelity_feature_1, ..., fidelity_feature_n)` to (mean, sem) results.
  
  The dataframe is retrieved via the `map_df` property. The data can be stored
  to an external store for future use by attaching it to an experiment using
  `experiment.attach_data()` (this requires a description to be set.)
class_docstr_tok: ["Class","storing","mapping-like","results","for","an","experiment",".","Data","is","stored","in","a","dataframe",",","and","auxiliary","information","(","(","key","name",",","default","value",")","pairs",")","are","stored","in","a","collection","of","MapKeyInfo","objects",".","Mapping-like","results","occur","whenever","a","metric","is","reported","as","a","collection","of","results",",","each","element","corresponding","to","a","tuple","of","values",".","The","simplest","case","is","a","sequence",".","For","instance","a","time","series","is","a","mapping","from","the","1-tuple","`","(","timestamp",")","`","to","(","mean",",","sem",")","results",".","Another","example",":","MultiFidelity","results",".","This","is","a","mapping","from","`","(","fidelity_feature_1",",","...",",","fidelity_feature_n",")","`","to","(","mean",",","sem",")","results",".","The","dataframe","is","retrieved","via","the","`","map_df","`","property",".","The","data","can","be","stored","to","an","external","store","for","future","use","by","attaching","it","to","an","experiment","using","`","experiment.attach_data","(",")","`","(","this","requires","a","description","to","be","set",".",")"]
docstr: Subsample the `map_key` column in an equally-spaced manner (if there is
  a `self.map_keys` is length one, then `map_key` can be set to None). The
  values of the `map_key` column are not taken into account, so this function
  is most reasonable when those values are equally-spaced. There are three
  ways that this can be done:
      1. If `keep_every = k` is set, then every kth row of the DataFrame in the
          `map_key` column is kept after grouping by `DEDUPLICATE_BY_COLUMNS`.
          In other words, every kth step of each (arm, metric) will be kept.
      2. If `limit_rows_per_group = n`, the method will find the (arm, metric)
          pair with the largest number of rows in the `map_key` column and select
          an approprioate `keep_every` such that each (arm, metric) has at most
          `n` rows in the `map_key` column.
      3. If `limit_rows_per_metric = n`, the method will select an
          appropriate `keep_every` such that the total number of rows per
          metric is less than `n`.
  If multiple of `keep_every`, `limit_rows_per_group`, `limit_rows_per_metric`,
  then the priority is in the order above: 1. `keep_every`,
  2. `limit_rows_per_group`, and 3. `limit_rows_per_metric`.
  
  Note that we want all curves to be subsampled with nearly the same spacing.
  Internally, the method converts `limit_rows_per_group` and
  `limit_rows_per_metric` to a `keep_every` quantity that will satisfy the
  original request.
  
  When `include_first_last` is True, then the method will use the `keep_every`
  as a guideline and for each group, produce (nearly) evenly spaced points that
  include the first and last points.
code: def subsample(
      self,
      map_key: Optional[str] = None,
      keep_every: Optional[int] = None,
      limit_rows_per_group: Optional[int] = None,
      limit_rows_per_metric: Optional[int] = None,
      include_first_last: bool = True,
  ) -> MapData:
      """Subsample the `map_key` column in an equally-spaced manner (if there is
      a `self.map_keys` is length one, then `map_key` can be set to None). The
      values of the `map_key` column are not taken into account, so this function
      is most reasonable when those values are equally-spaced. There are three
      ways that this can be done:
          1. If `keep_every = k` is set, then every kth row of the DataFrame in the
              `map_key` column is kept after grouping by `DEDUPLICATE_BY_COLUMNS`.
              In other words, every kth step of each (arm, metric) will be kept.
          2. If `limit_rows_per_group = n`, the method will find the (arm, metric)
              pair with the largest number of rows in the `map_key` column and select
              an approprioate `keep_every` such that each (arm, metric) has at most
              `n` rows in the `map_key` column.
          3. If `limit_rows_per_metric = n`, the method will select an
              appropriate `keep_every` such that the total number of rows per
              metric is less than `n`.
      If multiple of `keep_every`, `limit_rows_per_group`, `limit_rows_per_metric`,
      then the priority is in the order above: 1. `keep_every`,
      2. `limit_rows_per_group`, and 3. `limit_rows_per_metric`.
  
      Note that we want all curves to be subsampled with nearly the same spacing.
      Internally, the method converts `limit_rows_per_group` and
      `limit_rows_per_metric` to a `keep_every` quantity that will satisfy the
      original request.
  
      When `include_first_last` is True, then the method will use the `keep_every`
      as a guideline and for each group, produce (nearly) evenly spaced points that
      include the first and last points.
      """
      if (
          keep_every is None
          and limit_rows_per_group is None
          and limit_rows_per_metric is None
      ):
          logger.warning(
              "None of `keep_every`, `limit_rows_per_group`, or "
              "`limit_rows_per_metric` is specified. Returning the original data "
              "without subsampling."
          )
          return self
      if map_key is None:
          if len(self.map_keys) > 1:
              raise ValueError(
                  "More than one `map_key` found, cannot decide target to subsample."
              )
          map_key = self.map_keys[0]
      subsampled_metric_dfs = []
      for metric_name in self.map_df["metric_name"].unique():
          metric_map_df = self._filter_df(
              self.map_df, metric_names=[metric_name]
          )
          subsampled_metric_dfs.append(
              _subsample_one_metric(
                  metric_map_df,
                  map_key=map_key,
                  keep_every=keep_every,
                  limit_rows_per_group=limit_rows_per_group,
                  limit_rows_per_metric=limit_rows_per_metric,
                  include_first_last=include_first_last,
              )
          )
      subsampled_df: pd.DataFrame = pd.concat(subsampled_metric_dfs)
      return MapData(
          df=subsampled_df,
          map_key_infos=self.map_key_infos,
          description=self.description,
      )
  
imports: from __future__ import annotations
  from logging import Logger
  from typing import Any, Dict, Generic, Iterable, List, Optional, Sequence, Type, TypeVar
  import numpy
  import pandas
  from ax.core.data import Data
  from ax.core.types import TMapTrialEvaluation
  from ax.exceptions.core import UnsupportedError
  from ax.utils.common.base import SortableBase
  from ax.utils.common.docutils import copy_doc
  from ax.utils.common.equality import dataframe_equals
  from ax.utils.common.logger import get_logger
  from ax.utils.common.serialization import serialize_init_args, TClassDecoderRegistry, TDecoderRegistry
  from ax.utils.common.typeutils import checked_cast
label_desc: Use image node_id 16 for calling the MapData obj's underlying member method code with example usage: obj.subsample(map_key, keep_every, limit_rows_per_group, limit_rows_per_metric, include_first_last) and returns: MapData, self