code: def df_stability_report(
      df,
      settings: Settings | None | None = None,
      time_width=None,
      time_offset: int = 0,
      var_dtype=None,
      reference=None,
      split=None,
      **kwargs,
  ):
      """Create a data stability monitoring html report for given pandas or spark dataframe.
  
      :param df: input pandas/spark dataframe to be profiled and monitored over time.
      :param popmon.config.Settings settings: popmon configuration object
      :param time_width: bin width of time axis. str or number (ns). note: bin_specs takes precedence. (optional)
  
          .. code-block:: text
  
              Examples: '1w', 3600e9 (number of ns),
                        anything understood by pd.Timedelta(time_width).value
  
      :param time_offset: bin offset of time axis. str or number (ns). note: bin_specs takes precedence. (optional)
  
          .. code-block:: text
  
              Examples: '1-1-2020', 0 (number of ns since 1-1-1970),
                        anything parsed by pd.Timestamp(time_offset).value
  
      :param dict var_dtype: dictionary with specified datatype per feature. auto-guessed when not provided.
      :param reference: reference dataframe or histograms. default is None
      :return: dict with results of reporting pipeline
      """
  
      if settings is None:
          settings = Settings(**kwargs)
  
      if len(settings.time_axis) == 0:
          settings._set_time_axis_dataframe(df)
          logger.info(
              f'Time-axis automatically set to "{settings.time_axis}"'
          )
  
      if settings.time_axis not in df.columns:
          raise ValueError(
              f'time_axis  "{settings.time_axis}" not found in columns of dataframe.'
          )
  
      if (
          reference is not None
          and not isinstance(reference, dict)
          and settings.time_axis not in reference.columns
      ):
          raise ValueError(
              f'time_axis "{settings.time_axis}" not found in columns of reference dataframe.'
          )
  
      if settings.features is not None:
          # by now time_axis is defined. ensure that all histograms start with it.
          settings._ensure_features_time_axis()
  
      # interpret time_width and time_offset
      if time_width is not None:
          if not isinstance(time_width, (str, int, float)):
              raise TypeError
          if not isinstance(time_offset, (str, int, float)):
              raise TypeError
  
          settings._set_bin_specs_by_time_width_and_offset(
              time_width, time_offset
          )
  
      reference_hists = None
      if (
          settings.reference_type == "self"
          and split is not None
          and reference is None
      ):
          settings.reference_type = "self_split"
          reference, df = split_dataset(df, split, settings.time_axis)
  
      if reference is not None:
          if settings.reference_type != "self_split":
              settings.reference_type = "external"
  
          if isinstance(reference, dict):
              # 1. reference is dict of histograms
              # extract features and bin_specs from reference histograms
              reference_hists = reference
              if (
                  settings.features is not None
                  or settings.bin_specs != {}
              ):
                  raise ValueError(
                      "When providing a reference, the `features` and `bin_specs` settings should be default (as they are overriden)"
                  )
  
              settings.features = list(reference_hists.keys())
              settings.bin_specs = get_bin_specs(reference_hists)
          else:
              # 2. reference is pandas or spark dataframe
              # generate histograms and return updated features, bin_specs, time_axis, etc.
              (
                  reference_hists,
                  settings.features,
                  settings.bin_specs,
                  settings.time_axis,
                  var_dtype,
              ) = make_histograms(
                  reference,
                  settings.features,
                  settings.binning,
                  settings.bin_specs,
                  settings.time_axis,
                  var_dtype,
                  ret_specs=True,
              )
  
      # use the same features, bin_specs, time_axis, etc as for reference hists
      hists = make_histograms(
          df,
          features=settings.features,
          binning=settings.binning,
          bin_specs=settings.bin_specs,
          time_axis=settings.time_axis,
          var_dtype=var_dtype,
      )
  
      # generate data stability report
      return stability_report(
          hists=hists,
          settings=settings,
          reference=reference_hists,
      )
  
file_path: popmon/popmon/pipeline/report.py
imports: from __future__ import annotations
  import logging
  from histogrammar.dfinterface.make_histograms import get_bin_specs, make_histograms
  from popmon.config import Settings
  from popmon.pipeline.dataset_splitter import split_dataset
  from popmon.pipeline.report_pipelines import ReportPipe, get_report_pipeline_class
  from popmon.resources import templates_env
label_desc: Use image node_id 2 for calling a global function with example usage: df_stability_report(df, settings, time_width, time_offset, var_dtype, reference, split) and returns: stability_report