class_docstr: This module estimates the impact of holidays and their neighboring days
  given a raw holiday dataframe ``holiday_df``, and a time series containing
  the observed values to construct the baselines.
  It groups events with similar effects to several groups using kernel density estimation (KDE)
  and generates the grouped events in a dictionary of dataframes that is recognizable by
  `~greykite.algo.forecast.silverkite.forecast_silverkite.SilverkiteForecast`.
  
  Parameters
  ----------
  df : `pandas.DataFrame`
      Input time series that contains ``time_col`` and ``value_col``.
      The values will be used to construct baselines to estimate the holiday impact.
  time_col : `str`
      Name of the time column in ``df``.
  value_col : `str`
      Name of the value column in ``df``.
  holiday_df : `pandas.DataFrame`
      Input holiday dataframe that contains the dates and names of the holidays.
  holiday_date_col : `str`
      Name of the holiday date column in ``holiday_df``.
  holiday_name_col : `str`
      Name of the holiday name column in ``holiday_df``.
  holiday_impact_pre_num_days: `int`, default 0
      Default number of days before the holiday that will be modeled for holiday effect if the given holiday
      is not specified in ``holiday_impact_dict``.
  holiday_impact_post_num_days: `int`, default 0
      Default number of days after the holiday that will be modeled for holiday effect if the given holiday
      is not specified in ``holiday_impact_dict``.
  holiday_impact_dict : `Dict` [`str`, Any] or None, default None
      A dictionary containing the neighboring impacting days of a certain holiday. This overrides the
      default ``pre_num`` and ``post_num`` for each holiday specified here.
      The key is the name of the holiday matching those in the provided ``holiday_df``.
      The value is a tuple of two values indicating the number of neighboring days
      before and after the holiday. For example, a valid dictionary may look like:
  
          .. code-block:: python
  
              holiday_impact_dict = {
                  "Christmas Day": [3, 3],
                  "Memorial Day": [0, 0]
              }
  
  get_suffix_func : Callable or `str` or None, default "wd_we"
      A function that generates a suffix (usually a time feature e.g. "_WD" for weekday,
      "_WE" for weekend) given an input date.
      This can be used to estimate the interaction between floating holidays
      and on which day they are getting observed.
      We currently support two defaults:
  
          - "wd_we" to generate suffixes based on whether the day falls on weekday or weekend.
          - "dow_grouped" to generate three categories: ["_WD", "_Sat", "_Sun"].
  
      If None, no suffix is added.
  
  Attributes
  ----------
  expanded_holiday_df : `pandas.DataFrame`
      An expansion of ``holiday_df`` after adding the neighboring dates provided in
      ``holiday_impact_dict`` and the suffix generated by ``get_suffix_func``.
      For example, if ``"Christmas Day": [3, 3]`` and "wd_we" are used, events
      such as "Christmas Day_WD_plus_1_WE" or "Christmas Day_WD_minus_3_WD" will be generated
      for a Christmas that falls on Friday.
  baseline_offsets : `Tuple`[`int`] or None
      The offsets in days to calculate baselines for a given holiday.
      By default, the same days of the week before and after are used.
  use_relative_score : `bool` or None
      Whether to use relative or absolute score when estimating the holiday impact.
  clustering_method : `str` or None
      Clustering method used to group the holidays.
      Since we are doing 1-D clustering, current supported methods include
      (1) "kde" for kernel density estimation, and (2) "kmeans" for k-means clustering.
  bandwidth : `float` or None
      The bandwidth used in the kernel density estimation.
      Higher bandwidth results in less clusters.
      If None, it is automatically inferred with the ``bandwidth_multiplier`` factor.
  bandwidth_multiplier : `float` or None
      Multiplier to be multiplied to the kernel density estimation's default parameter calculated from
      `here<https://en.wikipedia.org/wiki/Kernel_density_estimation#A_rule-of-thumb_bandwidth_estimator>_`.
      This multiplier has been found useful in adjusting the default bandwidth parameter in many cases.
      Only used when ``bandwidth`` is not specified.
  kde : `KernelDensity` or None
      The `KernelDensity` object if ``clustering_method == "kde"``.
  n_clusters : `int` or None
      Number of clusters in the k-means algorithm.
  kmeans : `KMeans` or None
      The `KMeans` object if ``clustering_method == "kmeans"``.
  include_diagnostics : `bool` or None
      Whether to include ``kmeans_diagnostics`` and ``kmeans_plot`` in the output ``result_dict``.
  result_dict : `Dict`[`str`, Any] or None
      A dictionary that stores the scores and clustering results, with the following keys.
  
          - "holiday_inferrer": the `~greykite.algo.common.holiday_inferrer.HolidayInferrer`
              instance used for calculating the scores.
          - "score_result_original": a dictionary with keys being the names of all holiday events
              after expansion (i.e. the keys in ``expanded_holiday_df``), values being a list of scores
              of all dates corresponding to this event.
          - "score_result_avg_original": a dictionary with the same key as in
              ``result_dict["score_result_original"]``.
              But the values are the average scores of each event across all occurrences.
          - "score_result": same as ``result_dict["score_result_original"]``, but after removing
              holidays with inconsistent / negligible scores.
          - "score_result_avg": same as ``result_dict["score_result_original"]``, but after removing
              holidays with inconsistent / negligible scores.
          - "daily_event_df_dict_with_score": a dictionary of dataframes.
              Key is the group name ``"holiday_group_{k}"``.
              Value is a dataframe of all holiday events in this group, containing 4 columns:
              "date" (``EVENT_DF_DATE_COL``), "event_name" (``EVENT_DF_LABEL_COL``), "original_name", "avg_score".
          - "daily_event_df_dict": a dictionary of dataframes that is ready to use in `SilverkiteForecast`.
              Contains 2 keys: ``EVENT_DF_DATE_COL`` and ``EVENT_DF_LABEL_COL``.
          - "kde_cutoffs": a list of `float`, the cutoffs returned by the kernel density clustering.
          - "kde_res": a dataframe that contains "score" and "density" from the kernel density estimation.
          - "kde_plot": a plot of the kernel density estimation.
          - "kmeans_diagnostics": a dataframe containing metrics for different number of clusters.
              Columns are:
  
                  - "k": number of clusters;
                  - "wsse": within-cluster sum of squared error (lower is better);
                  - "sil_score": Silhouette coefficient, a value between [-1, 1] that describes
                      the separation of clusters (higher is better).
  
              Only generated when ``include_diagnostics`` is True. See `group_holidays` for details.
          - "kmeans_plot": a plot visualizing how the diagnostic metrics change over K.
              Only generated when ``include_diagnostics`` is True. See `group_holidays` for details.
class_docstr_tok: ["This","module","estimates","the","impact","of","holidays","and","their","neighboring","days","given","a","raw","holiday","dataframe","``","holiday_df","``",",","and","a","time","series","containing","the","observed","values","to","construct","the","baselines",".","It","groups","events","with","similar","effects","to","several","groups","using","kernel","density","estimation","(","KDE",")","and","generates","the","grouped","events","in","a","dictionary","of","dataframes","that","is","recognizable","by","`","~greykite.algo.forecast.silverkite.forecast_silverkite.SilverkiteForecast","`",".","Parameters","--","--","--","--","--","df",":","`","pandas.DataFrame","`","Input","time","series","that","contains","``","time_col","``","and","``","value_col","``",".","The","values","will","be","used","to","construct","baselines","to","estimate","the","holiday","impact",".","time_col",":","`","str","`","Name","of","the","time","column","in","``","df","``",".","value_col",":","`","str","`","Name","of","the","value","column","in","``","df","``",".","holiday_df",":","`","pandas.DataFrame","`","Input","holiday","dataframe","that","contains","the","dates","and","names","of","the","holidays",".","holiday_date_col",":","`","str","`","Name","of","the","holiday","date","column","in","``","holiday_df","``",".","holiday_name_col",":","`","str","`","Name","of","the","holiday","name","column","in","``","holiday_df","``",".","holiday_impact_pre_num_days",":","`","int","`",",","default","0","Default","number","of","days","before","the","holiday","that","will","be","modeled","for","holiday","effect","if","the","given","holiday","is","not","specified","in","``","holiday_impact_dict","``",".","holiday_impact_post_num_days",":","`","int","`",",","default","0","Default","number","of","days","after","the","holiday","that","will","be","modeled","for","holiday","effect","if","the","given","holiday","is","not","specified","in","``","holiday_impact_dict","``",".","holiday_impact_dict",":","`","Dict","`","[","`","str","`",",","Any","]","or","None",",","default","None","A","dictionary","containing","the","neighboring","impacting","days","of","a","certain","holiday",".","This","overrides","the","default","``","pre_num","``","and","``","post_num","``","for","each","holiday","specified","here",".","The","key","is","the","name","of","the","holiday","matching","those","in","the","provided","``","holiday_df","``",".","The","value","is","a","tuple","of","two","values","indicating","the","number","of","neighboring","days","before","and","after","the","holiday",".","For","example",",","a","valid","dictionary","may","look","like",":","..","code-block",":",":","python","holiday_impact_dict","=","{","``","Christmas","Day","''",":","[","3",",","3","]",",","``","Memorial","Day","''",":","[","0",",","0","]","}","get_suffix_func",":","Callable","or","`","str","`","or","None",",","default","``","wd_we","''","A","function","that","generates","a","suffix","(","usually","a","time","feature","e.g",".","``","_WD","''","for","weekday",",","``","_WE","''","for","weekend",")","given","an","input","date",".","This","can","be","used","to","estimate","the","interaction","between","floating","holidays","and","on","which","day","they","are","getting","observed",".","We","currently","support","two","defaults",":","-","``","wd_we","''","to","generate","suffixes","based","on","whether","the","day","falls","on","weekday","or","weekend",".","-","``","dow_grouped","''","to","generate","three","categories",":","[","``","_WD","''",",","``","_Sat","''",",","``","_Sun","''","]",".","If","None",",","no","suffix","is","added",".","Attributes","--","--","--","--","--","expanded_holiday_df",":","`","pandas.DataFrame","`","An","expansion","of","``","holiday_df","``","after","adding","the","neighboring","dates","provided","in","``","holiday_impact_dict","``","and","the","suffix","generated","by","``","get_suffix_func","``",".","For","example",",","if","``","``","Christmas","Day","''",":","[","3",",","3","]","``","and","``","wd_we","''","are","used",",","events","such","as","``","Christmas","Day_WD_plus_1_WE","''","or","``","Christmas","Day_WD_minus_3_WD","''","will","be","generated","for","a","Christmas","that","falls","on","Friday",".","baseline_offsets",":","`","Tuple","`","[","`","int","`","]","or","None","The","offsets","in","days","to","calculate","baselines","for","a","given","holiday",".","By","default",",","the","same","days","of","the","week","before","and","after","are","used",".","use_relative_score",":","`","bool","`","or","None","Whether","to","use","relative","or","absolute","score","when","estimating","the","holiday","impact",".","clustering_method",":","`","str","`","or","None","Clustering","method","used","to","group","the","holidays",".","Since","we","are","doing","1-D","clustering",",","current","supported","methods","include","(","1",")","``","kde","''","for","kernel","density","estimation",",","and","(","2",")","``","kmeans","''","for","k-means","clustering",".","bandwidth",":","`","float","`","or","None","The","bandwidth","used","in","the","kernel","density","estimation",".","Higher","bandwidth","results","in","less","clusters",".","If","None",",","it","is","automatically","inferred","with","the","``","bandwidth_multiplier","``","factor",".","bandwidth_multiplier",":","`","float","`","or","None","Multiplier","to","be","multiplied","to","the","kernel","density","estimation","'s","default","parameter","calculated","from","`","here","<","https",":","\/\/en.wikipedia.org\/wiki\/Kernel_density_estimation","#","A_rule-of-thumb_bandwidth_estimator",">","_","`",".","This","multiplier","has","been","found","useful","in","adjusting","the","default","bandwidth","parameter","in","many","cases",".","Only","used","when","``","bandwidth","``","is","not","specified",".","kde",":","`","KernelDensity","`","or","None","The","`","KernelDensity","`","object","if","``","clustering_method","==","``","kde","''","``",".","n_clusters",":","`","int","`","or","None","Number","of","clusters","in","the","k-means","algorithm",".","kmeans",":","`","KMeans","`","or","None","The","`","KMeans","`","object","if","``","clustering_method","==","``","kmeans","''","``",".","include_diagnostics",":","`","bool","`","or","None","Whether","to","include","``","kmeans_diagnostics","``","and","``","kmeans_plot","``","in","the","output","``","result_dict","``",".","result_dict",":","`","Dict","`","[","`","str","`",",","Any","]","or","None","A","dictionary","that","stores","the","scores","and","clustering","results",",","with","the","following","keys",".","-","``","holiday_inferrer","''",":","the","`","~greykite.algo.common.holiday_inferrer.HolidayInferrer","`","instance","used","for","calculating","the","scores",".","-","``","score_result_original","''",":","a","dictionary","with","keys","being","the","names","of","all","holiday","events","after","expansion","(","i.e",".","the","keys","in","``","expanded_holiday_df","``",")",",","values","being","a","list","of","scores","of","all","dates","corresponding","to","this","event",".","-","``","score_result_avg_original","''",":","a","dictionary","with","the","same","key","as","in","``","result_dict","[","``","score_result_original","''","]","``",".","But","the","values","are","the","average","scores","of","each","event","across","all","occurrences",".","-","``","score_result","''",":","same","as","``","result_dict","[","``","score_result_original","''","]","``",",","but","after","removing","holidays","with","inconsistent","\/","negligible","scores",".","-","``","score_result_avg","''",":","same","as","``","result_dict","[","``","score_result_original","''","]","``",",","but","after","removing","holidays","with","inconsistent","\/","negligible","scores",".","-","``","daily_event_df_dict_with_score","''",":","a","dictionary","of","dataframes",".","Key","is","the","group","name","``","``","holiday_group_","{","k","}","''","``",".","Value","is","a","dataframe","of","all","holiday","events","in","this","group",",","containing","4","columns",":","``","date","''","(","``","EVENT_DF_DATE_COL","``",")",",","``","event_name","''","(","``","EVENT_DF_LABEL_COL","``",")",",","``","original_name","''",",","``","avg_score","''",".","-","``","daily_event_df_dict","''",":","a","dictionary","of","dataframes","that","is","ready","to","use","in","`","SilverkiteForecast","`",".","Contains","2","keys",":","``","EVENT_DF_DATE_COL","``","and","``","EVENT_DF_LABEL_COL","``",".","-","``","kde_cutoffs","''",":","a","list","of","`","float","`",",","the","cutoffs","returned","by","the","kernel","density","clustering",".","-","``","kde_res","''",":","a","dataframe","that","contains","``","score","''","and","``","density","''","from","the","kernel","density","estimation",".","-","``","kde_plot","''",":","a","plot","of","the","kernel","density","estimation",".","-","``","kmeans_diagnostics","''",":","a","dataframe","containing","metrics","for","different","number","of","clusters",".","Columns","are",":","-","``","k","''",":","number","of","clusters",";","-","``","wsse","''",":","within-cluster","sum","of","squared","error","(","lower","is","better",")",";","-","``","sil_score","''",":","Silhouette","coefficient",",","a","value","between","[","-1",",","1","]","that","describes","the","separation","of","clusters","(","higher","is","better",")",".","Only","generated","when","``","include_diagnostics","``","is","True",".","See","`","group_holidays","`","for","details",".","-","``","kmeans_plot","''",":","a","plot","visualizing","how","the","diagnostic","metrics","change","over","K.","Only","generated","when","``","include_diagnostics","``","is","True",".","See","`","group_holidays","`","for","details","."]
code: def __init__(
      self,
      df: pd.DataFrame,
      time_col: str,
      value_col: str,
      holiday_df: pd.DataFrame,
      holiday_date_col: str,
      holiday_name_col: str,
      holiday_impact_pre_num_days: int = 0,
      holiday_impact_post_num_days: int = 0,
      holiday_impact_dict: Optional[Dict[str, Tuple[int, int]]] = None,
      get_suffix_func: Optional[Union[Callable, str]] = "wd_we",
  ):
      self.df = df.copy()
      self.time_col = time_col
      self.value_col = value_col
      self.holiday_df = holiday_df.copy()
      self.holiday_date_col = holiday_date_col
      self.holiday_name_col = holiday_name_col
      self.holiday_impact_pre_num_days = holiday_impact_pre_num_days
      self.holiday_impact_post_num_days = holiday_impact_post_num_days
      if holiday_impact_dict is None:
          holiday_impact_dict = {}
      self.holiday_impact_dict = holiday_impact_dict.copy()
      self.get_suffix_func = get_suffix_func
  
      # Derived attributes.
      # Casts time columns to `datetime`.
      self.df[time_col] = pd.to_datetime(self.df[time_col])
      self.holiday_df[holiday_date_col] = pd.to_datetime(
          self.holiday_df[holiday_date_col]
      )
      # Creates `HOLIDAY_DATE_COL` and `HOLIDAY_NAME_COL` (if not exists) to be recognized by `HolidayInferrer`.
      self.holiday_df[HOLIDAY_DATE_COL] = self.holiday_df[
          self.holiday_date_col
      ]
      self.holiday_df[HOLIDAY_NAME_COL] = self.holiday_df[
          self.holiday_name_col
      ]
  
      # Other attributes that are not needed for initialization.
      self.baseline_offsets: Optional[Tuple[int, int]] = None
      self.use_relative_score: Optional[bool] = None
      self.clustering_method: Optional[str] = None
      self.bandwidth: Optional[float] = None
      self.bandwidth_multiplier: Optional[float] = None
      self.kde: Optional[KernelDensity] = None
      self.n_clusters: Optional[int] = None
      self.kmeans: Optional[KMeans] = None
      self.include_diagnostics: Optional[bool] = None
      # Result dictionary will be populated after the scoring and grouping functions are run.
      self.result_dict: Optional[Dict[str, Any]] = None
  
      # Expands `holiday_df` to include neighboring days
      # and suffixes (e.g. "_WD" for weekdays, "_Sat" for Saturdays).
      self.expanded_holiday_df = self.expand_holiday_df_with_suffix(
          holiday_df=self.holiday_df,
          holiday_date_col=HOLIDAY_DATE_COL,
          holiday_name_col=HOLIDAY_NAME_COL,
          holiday_impact_pre_num_days=self.holiday_impact_pre_num_days,
          holiday_impact_post_num_days=self.holiday_impact_post_num_days,
          holiday_impact_dict=self.holiday_impact_dict,
          get_suffix_func=self.get_suffix_func,
      )
  
imports: from datetime import timedelta
  from typing import Any
  from typing import Callable
  from typing import Dict
  from typing import List
  from typing import Optional
  from typing import Tuple
  from typing import Union
  import numpy
  import pandas
  from IPython.display import display
  from sklearn.cluster import KMeans
  from sklearn.metrics import silhouette_score
  from sklearn.neighbors import KernelDensity
  from greykite.algo.common.holiday_inferrer import HolidayInferrer
  from greykite.algo.common.holiday_utils import HOLIDAY_DATE_COL
  from greykite.algo.common.holiday_utils import HOLIDAY_NAME_COL
  from greykite.algo.common.holiday_utils import get_dow_grouped_suffix
  from greykite.algo.common.holiday_utils import get_weekday_weekend_suffix
  from greykite.common.constants import EVENT_DF_DATE_COL
  from greykite.common.constants import EVENT_DF_LABEL_COL
  from greykite.common.logging import LoggingLevelEnum
  from greykite.common.logging import log_message
  from greykite.common.viz.timeseries_plotting import plot_multivariate
label_desc: Use image node_id 1 to create a new HolidayGrouper object  with example: obj = HolidayGrouper(df, time_col, value_col, holiday_df, holiday_date_col, holiday_name_col, holiday_impact_pre_num_days, holiday_impact_post_num_days, holiday_impact_dict, get_suffix_func)