code: def add_daily_events(
      df,
      event_df_dict,
      date_col=cst.EVENT_DF_DATE_COL,
      regular_day_label=cst.EVENT_DEFAULT,
      neighbor_impact=None,
      shifted_effect=None,
  ):
      """For each key of event_df_dict, it adds a new column to a data frame (df)
      with a date column (date_col).
      Each new column will represent the events given for that key.
      This function also generates 3 binary event flags
      ``IS_EVENT_EXACT_COL``, ``IS_EVENT_ADJACENT_COL`` and ``IS_EVENT_COL``
      given the information in ``event_df_dict`` with the following logic:
  
          (1) If the key contains "_minus_" or "_plus_", that means the event
          was generated by the ``add_event_window`` function, and it is a
          neighboring day of some exact event day.
          In this case, ``IS_EVENT_ADJACENT_COL`` will be 1 for all days in this key.
  
          (2) Otherwise the key indicates that it is on the exact event day being modeled.
          In this case, ``IS_EVENT_EXACT_COL`` will be 1 for all days in this key.
  
          (3) If a date appears in both types of keys, both above columns will be 1.
  
          (4) ``IS_EVENT_COL`` is 1 for all dates in the provided ``event_df_dict``.
  
      Parameters
      ----------
      df : `pandas.DataFrame`
          The data frame which has a date column.
      event_df_dict : `dict` [`str`, `pandas.DataFrame`]
          A dictionary of data frames, each representing events data
          for the corresponding key.
          Values are DataFrames with two columns:
  
              - The first column contains the date. Must be at the same
                frequency as ``df[date_col]`` for proper join. Must be in a
                format recognized by `pandas.to_datetime`.
              - The second column contains the event label for each date
  
      date_col : `str`
          Column name in ``df`` that contains the dates for joining against
          the events in ``event_df_dict``.
      regular_day_label : `str`
          The label used for regular days which are not "events".
      neighbor_impact : `int`, `list` [`int`], callable or None, default None
          The impact of neighboring timestamps of the events in ``event_df_dict``.
          This is for daily events so the units below are all in days.
  
          For example, if the data is weekly ("W-SUN") and an event is daily,
          it may not exactly fall on the weekly date.
          But you can specify for New Year's day on 1-1, it affects all dates
          in the week, e.g. 12-31, 1-1, ..., 1-6, then it will be mapped to the weekly date.
          In this case you may want to map a daily event's date to a few dates,
          and can specify
          ``neighbor_impact=lambda x: [x-timedelta(days=x.isocalendar()[2]-1) + timedelta(days=i) for i in range(7)]``.
  
          Another example is that the data is rolling 7 day daily data,
          thus a holiday may affect the t, t+1, ..., t+6 dates.
          You can specify ``neighbor_impact=7``.
  
          If input is `int`, the mapping is t, t+1, ..., t+neighbor_impact-1.
          If input is `list`, the mapping is [t+x for x in neighbor_impact].
          If input is a function, it maps each daily event's date to a list of dates.
      shifted_effect : `list` [`str`] or None, default None
          Additional neighbor events based on given events.
          For example, passing ["-1D", "7D"] will add extra daily events which are 1 day before
          and 7 days after the given events.
          Offset format is {d}{freq} with any integer plus a frequency string. Must be parsable by pandas ``to_offset``.
          The new events' names will be the current events' names with suffix "{offset}_before" or "{offset}_after".
          For example, if we have an event named "US_Christmas Day",
          a "7D" shift will have name "US_Christmas Day_7D_after".
          This is useful when you expect an offset of the current holidays also has impact on the
          time series, or you want to interact the lagged terms with autoregression.
          If ``neighbor_impact`` is also specified, this will be applied after adding neighboring days.
  
      Returns
      -------
      df_daily_events : `pandas.DataFrame`
          An augmented data frame version of df with new label columns --
          one for each key of ``event_df_dict``.
      """
      df[date_col] = pd.to_datetime(df[date_col])
      get_neighbor_days_func = None
      new_event_cols = [
          cst.IS_EVENT_EXACT_COL,
          cst.IS_EVENT_ADJACENT_COL,
          cst.IS_EVENT_COL,
      ]
      event_flag_df_list = []
      if neighbor_impact is not None:
          if isinstance(neighbor_impact, int):
              neighbor_impact = sorted([neighbor_impact, 0])
              neighbor_impact[1] += 1
  
              def get_neighbor_days_func(date):
                  return [
                      date + timedelta(days=d)
                      for d in range(*neighbor_impact)
                  ]
  
          elif isinstance(neighbor_impact, list):
              if 0 not in neighbor_impact:
                  neighbor_impact = sorted(neighbor_impact + [0])
  
              def get_neighbor_days_func(date):
                  return [
                      date + timedelta(days=d) for d in neighbor_impact
                  ]
  
          else:
              get_neighbor_days_func = neighbor_impact
      for label, event_df in event_df_dict.items():
          event_df = (
              event_df.copy().drop_duplicates()
          )  # Makes a copy to avoid modifying input
          new_col = f"{cst.EVENT_PREFIX}_{label}"
          event_df.columns = [date_col, new_col]
          event_df[date_col] = pd.to_datetime(event_df[date_col])
          # Handles neighboring impact.
          if get_neighbor_days_func is not None:
              new_event_df = None
              for i in range(len(event_df)):
                  mapped_dates = get_neighbor_days_func(
                      event_df["date"].iloc[i]
                  )
                  new_event_df = pd.concat(
                      [
                          new_event_df,
                          event_df.iloc[[i] * len(mapped_dates)].assign(
                              **{date_col: mapped_dates}
                          ),
                      ],
                      axis=0,
                  )
              event_df = new_event_df.drop_duplicates().reset_index(
                  drop=True
              )
          df = df.merge(event_df, on=date_col, how="left")
          df[new_col] = df[new_col].fillna(regular_day_label)
          # Adds neighbor events if requested.
          new_event_dfs = []
          if shifted_effect is not None:
              for lag in shifted_effect:
                  num, freq = split_offset_str(lag)
                  num = int(num)
                  if num != 0:
                      lag_offset = to_offset(lag)
                      new_event_df = event_df.copy()
                      new_event_df[date_col] += lag_offset
                      suffix = (
                          cst.EVENT_SHIFTED_SUFFIX_BEFORE
                          if num < 0
                          else cst.EVENT_SHIFTED_SUFFIX_AFTER
                      )
                      new_col = f"{cst.EVENT_PREFIX}_{label}_{abs(num)}{freq}{suffix}"
                      new_event_df.columns = [date_col, new_col]
                      new_event_df[
                          new_col
                      ] += f"_{abs(num)}{freq}{suffix}"
                      df = df.merge(
                          new_event_df, on=date_col, how="left"
                      )
                      df[new_col] = df[new_col].fillna(
                          regular_day_label
                      )
                      new_event_dfs.append(new_event_df)
          # Generates event indicators.
          # `augmented_event_df` contains `date_col` and three event indicator columns to be added to `df`.
          for event_df_temp in [event_df] + new_event_dfs:
              augmented_event_df = event_df_temp[
                  [date_col]
              ].drop_duplicates()
              is_event_adjacent = (
                  "_minus_" in label or "_plus_" in label
              )
              augmented_event_df[cst.IS_EVENT_EXACT_COL] = (
                  0 if is_event_adjacent else 1
              )
              augmented_event_df[cst.IS_EVENT_ADJACENT_COL] = (
                  1 if is_event_adjacent else 0
              )
              augmented_event_df[
                  cst.IS_EVENT_COL
              ] = 1  # In either case, `IS_EVENT_COL` is 1.
              event_flag_df_list.append(augmented_event_df)
  
      event_flag_df = pd.concat(event_flag_df_list)
      # Sets a day as 1 if it is marked by any of the keys in `event_df_dict`.
      event_flag_df = (
          event_flag_df.groupby(by=date_col)[new_event_cols]
          .sum()
          .reset_index(drop=False)
      )
      event_flag_df[new_event_cols] = 1 * (
          event_flag_df[new_event_cols] > 0
      )
      # Joins the new event indicators to `df`.
      df = df.merge(event_flag_df, on=date_col, how="left")
      df[new_event_cols] = df[new_event_cols].fillna(0)
  
      return df
  
imports: import math
  from datetime import datetime
  from datetime import timedelta
  import numpy
  import pandas
  import pytz
  from holidays_ext import get_holidays
  from pandas.tseries.frequencies import to_offset
  from scipy.special import expit
  from greykite.common import constants
  from greykite.common.python_utils import split_offset_str
label_desc: Use image node_id 15 for calling a global function with example usage: add_daily_events(df, event_df_dict, date_col, regular_day_label, neighbor_impact, shifted_effect) and returns: df, unknown, unknown