code: def _postprocess_dataframe(df):
      """Apply some post-processing to an ouput dataframe (e.g. rounding).
  
      Whether and how rounding is applied is governed by options specified in
      `pingouin.options`. The default rounding (number of decimals) is
      determined by `pingouin.options['round']`. You can specify rounding for a
      given column name by the option `'round.column.<colname>'`, e.g.
      `'round.column.CI95%'`. Analogously, `'round.row.<rowname>'` also works
      (where `rowname`) refers to the pandas index), as well as
      `'round.cell.[<rolname>]x[<colname]'`. A cell-based option is used,
      if available; if not, a column-based option is used, if
      available; if not, a row-based option is used, if available; if not,
      the default is used. (Default `pingouin.options['round'] = None`,
      i.e. no rounding is applied.)
  
      If a round option is `callable` instead of `int`, then it will be called,
      and the return value stored in the cell.
  
      Post-processing is applied on a copy of the DataFrame, leaving the
      original DataFrame untouched.
  
      This is an internal function (no public API).
  
      Parameters
      ----------
      df : :py:class:`pandas.DataFrame`
          Dataframe to apply post-processing to (e.g. ANOVA summary)
  
      Returns
      ----------
      df : :py:class:`pandas.DataFrame`
          Dataframe with post-processing applied
      """
      df = df.copy()
      for row, col in it.product(df.index, df.columns):
          round_option = _get_round_setting_for(row, col)
          if round_option is None:
              continue
          if callable(round_option):
              newval = round_option(df.at[row, col])
              # ensure that dtype changes are processed
              df[col] = df[col].astype(type(newval))
              df.at[row, col] = newval
              continue
          if isinstance(df.at[row, col], bool):
              # No rounding if value is a boolean
              continue
          is_number = isinstance(df.at[row, col], numbers.Number)
          is_array = isinstance(df.at[row, col], np.ndarray)
          if not any([is_number, is_array]):
              # No rounding if value is not a Number or an array
              continue
          if is_array:
              is_float_array = issubclass(
                  df.at[row, col].dtype.type, np.floating
              )
              if not is_float_array:
                  # No rounding if value is not a float array
                  continue
          df.at[row, col] = np.round(
              df.at[row, col], decimals=round_option
          )
      return df
  
file_path: pingouin/pingouin/utils.py
imports: import numbers
  import numpy
  import pandas
  import itertools
  import collections.abc
  from tabulate import tabulate
  from .config import options
label_desc: Use image node_id 3 for calling a global function with example usage: _postprocess_dataframe(df) and returns: df