class_docstr: Interface for Pandas GroupBy operations allowing specified group order.
  
  Writing our own class to do this has a few advantages:
  - It constrains the interface between Plot and Stat/Move objects
  - It allows control over the row order of the GroupBy result, which is
    important when using in the context of some Move operations (dodge, stack, ...)
  - It simplifies some complexities regarding the return type and Index contents
    one encounters with Pandas, especially for DataFrame -> DataFrame applies
  - It increases future flexibility regarding alternate DataFrame libraries
class_docstr_tok: ["Interface","for","Pandas","GroupBy","operations","allowing","specified","group","order",".","Writing","our","own","class","to","do","this","has","a","few","advantages",":","-","It","constrains","the","interface","between","Plot","and","Stat\/Move","objects","-","It","allows","control","over","the","row","order","of","the","GroupBy","result",",","which","is","important","when","using","in","the","context","of","some","Move","operations","(","dodge",",","stack",",","...",")","-","It","simplifies","some","complexities","regarding","the","return","type","and","Index","contents","one","encounters","with","Pandas",",","especially","for","DataFrame","-",">","DataFrame","applies","-","It","increases","future","flexibility","regarding","alternate","DataFrame","libraries"]
docstr: Reduce each group to a single row in the output.
  
  The output will have a row for each unique combination of the grouping
  variable levels with null values for the aggregated variable(s) where
  those combinations do not appear in the dataset.
docstr_tok: ["Reduce","each","group","to","a","single","row","in","the","output",".","The","output","will","have","a","row","for","each","unique","combination","of","the","grouping","variable","levels","with","null","values","for","the","aggregated","variable","(","s",")","where","those","combinations","do","not","appear","in","the","dataset","."]
code: def agg(self, data: DataFrame, *args, **kwargs) -> DataFrame:
      """
      Reduce each group to a single row in the output.
  
      The output will have a row for each unique combination of the grouping
      variable levels with null values for the aggregated variable(s) where
      those combinations do not appear in the dataset.
  
      """
      grouper, groups = self._get_groups(data)
  
      if not grouper:
          # We will need to see whether there are valid usecases that end up here
          raise ValueError(
              "No grouping variables are present in dataframe"
          )
  
      res = (
          data.groupby(grouper, sort=False, observed=False)
          .agg(*args, **kwargs)
          .reindex(groups)
          .reset_index()
          .pipe(self._reorder_columns, data)
      )
  
      return res
  
file_path: seaborn/seaborn/_core/groupby.py
imports: from __future__ import annotations
  from typing import cast, Iterable
  import pandas
  from seaborn._core.rules import categorical_order
  from typing import TYPE_CHECKING
label_desc: Use image node_id 4 for calling the GroupBy obj's underlying member method code with example usage: obj.agg(data) and returns: res