code: def design_mat_from_formula(
      df: pd.DataFrame,
      model_formula_str: str,
      y_col: Optional[str] = None,
      pred_cols: Optional[List[str]] = None,
      remove_intercept: bool = False,
  ) -> Dict:
      """Given a formula it extracts the response vector (y)
      and builds the design matrix (x_mat).
  
      Parameters
      ----------
      df : `pandas.DataFrame`
          A dataframe with the response vector (y) and the feature columns (x_mat).
      model_formula_str : `str`
          A formula string e.g. "y~x1+x2+x3*x4".
          This is similar to R formulas.
          See https://patsy.readthedocs.io/en/latest/formulas.html#how-formulas-work.
      y_col : `str` or None, default None
          The column name which has the value of interest to be forecasted.
          If the model_formula_str is not passed, y_col e.g. ["y"] is used
          as the response vector column.
      pred_cols : `list` [`str`] or None, default None
          The names of the feature columns.
          If the model_formula_str is not passed, pred_cols e.g.
          ["x1", "x2", "x3"] is used as the design matrix columns.
      remove_intercept : `bool`, default False
          Whether to remove explicit and implicit intercepts.
          By default, `patsy` will make the design matrix always full rank.
          It will always include an intercept term unless we specify "-1" or "+0".
          However, if there are categorical variables, even we specify "-1" or "+0",
          it will include an implicit intercept by adding all levels of a categorical
          variable into the design matrix.
          Sometimes we don't want this to happen.
          Setting this parameter to True will remove both explicit and implicit intercepts.
  
      Returns
      -------
      result : `dict`
          Result dictionary with the following keys:
  
              - "y": The response vector.
              - "y_col": Name of the response column (y).
              - "x_mat": A design matrix.
              - "pred_cols": Name of the columns of the design matrix (x_mat).
              - "x_design_info": Information for design matrix.
              - "drop_intercept_col": The intercept column to be dropped.
  
      """
      intercept_col = None
      if model_formula_str is not None:
          y, x_mat = patsy.dmatrices(
              model_formula_str, data=df, return_type="dataframe"
          )
          x_design_info = x_mat.design_info
          if remove_intercept:
              intercept_col = get_intercept_col_from_design_mat(
                  x_mat=x_mat
              )
              if intercept_col is not None:
                  x_mat = x_mat.drop(columns=intercept_col)
          pred_cols = list(x_mat.columns)
          # Gets the response column name using "~" location.
          y_col = (
              re.search("(.*)~", model_formula_str).group(1).strip(" ")
          )
          y = y[y.columns[0]]
      elif y_col is not None and pred_cols is not None:
          y = df[y_col]
          x_mat = df[pred_cols]
          x_design_info = None
      else:
          raise Exception(
              f"Either provide a model expression or both y_col and pred_cols."
          )
  
      return {
          "y": y,
          "y_col": y_col,
          "x_mat": x_mat,
          "pred_cols": pred_cols,
          "x_design_info": x_design_info,
          "drop_intercept_col": intercept_col,
      }
  
imports: import random
  import re
  import traceback
  import warnings
  from typing import Dict
  from typing import List
  from typing import Optional
  import matplotlib
  import numpy
  import pandas
  import patsy
  import scipy
  import statsmodels.api
  from pandas.plotting import register_matplotlib_converters
  from sklearn.ensemble import GradientBoostingRegressor
  from sklearn.ensemble import RandomForestRegressor
  from sklearn.linear_model import ElasticNetCV
  from sklearn.linear_model import LarsCV
  from sklearn.linear_model import LassoCV
  from sklearn.linear_model import LassoLarsCV
  from sklearn.linear_model import RidgeCV
  from sklearn.linear_model import SGDRegressor
  from greykite.algo.common.l1_quantile_regression import QuantileRegression
  from greykite.algo.uncertainty.conditional.conf_interval import conf_interval
  from greykite.algo.uncertainty.conditional.conf_interval import predict_ci
  from greykite.common.constants import RESIDUAL_COL
  from greykite.common.constants import R2_null_model_score
  from greykite.common.evaluation import calc_pred_err
  from greykite.common.evaluation import r2_null_model_score
  from greykite.common.features.normalize import normalize_df
  from greykite.common.logging import LoggingLevelEnum
  from greykite.common.logging import log_message
  from greykite.common.python_utils import group_strs_with_regex_patterns
  from greykite.common.viz.timeseries_plotting import plot_multivariate
  import matplotlib.pyplot
label_desc: Use image node_id 2 for calling a global function with example usage: design_mat_from_formula(df, model_formula_str, y_col, pred_cols, remove_intercept) and returns: dict