class_docstr: Class to build a VAR model
      
class_docstr_tok: ["Class","to","build","a","VAR","model"]
docstr:  This builds a VAR model given a multivariate time series data frame with time as the Index.
  
  :param ts_df The time series data to be used for fitting the model. Note that the input can be
  a data frame with one column or multiple cols or a multivariate array. However, the first column
  must be the target variable. You must include only Time Series data in it. DO NOT include
  "Non-Stationary" or "Trendy" data. Make sure your Time Series is "Stationary" before you send
  it in!! If not, this will give spurious results.
  :type ts_df pd.DataFrame
  
  :param target_col The column name of the target time series that needs to be modeled.
  All other columns will be considered as exogenous variables (if applicable to method)
  :type target_col str
  
  :param cv: Number of folds to use for cross validation.
  Number of observations in the Validation set for each fold = forecast period
  If None, a single fold is used
  :type cv Optional[int]
  
  :rtype object
docstr_tok: ["This","builds","a","VAR","model","given","a","multivariate","time","series","data","frame","with","time","as","the","Index",".",":","param","ts_df","The","time","series","data","to","be","used","for","fitting","the","model",".","Note","that","the","input","can","be","a","data","frame","with","one","column","or","multiple","cols","or","a","multivariate","array",".","However",",","the","first","column","must","be","the","target","variable",".","You","must","include","only","Time","Series","data","in","it",".","DO","NOT","include","''","Non-Stationary","''","or","``","Trendy","''","data",".","Make","sure","your","Time","Series","is","``","Stationary","''","before","you","send","it","in","!","!","If","not",",","this","will","give","spurious","results",".",":","type","ts_df","pd.DataFrame",":","param","target_col","The","column","name","of","the","target","time","series","that","needs","to","be","modeled",".","All","other","columns","will","be","considered","as","exogenous","variables","(","if","applicable","to","method",")",":","type","target_col","str",":","param","cv",":","Number","of","folds","to","use","for","cross","validation",".","Number","of","observations","in","the","Validation","set","for","each","fold","=","forecast","period","If","None",",","a","single","fold","is","used",":","type","cv","Optional","[","int","]",":","rtype","object"]
code: def fit(
      self,
      ts_df: pd.DataFrame,
      target_col: str,
      cv: Optional[int] = None,
  ) -> object:
      """
       This builds a VAR model given a multivariate time series data frame with time as the Index.
  
      :param ts_df The time series data to be used for fitting the model. Note that the input can be
      a data frame with one column or multiple cols or a multivariate array. However, the first column
      must be the target variable. You must include only Time Series data in it. DO NOT include
      "Non-Stationary" or "Trendy" data. Make sure your Time Series is "Stationary" before you send
      it in!! If not, this will give spurious results.
      :type ts_df pd.DataFrame
  
      :param target_col The column name of the target time series that needs to be modeled.
      All other columns will be considered as exogenous variables (if applicable to method)
      :type target_col str
  
      :param cv: Number of folds to use for cross validation.
      Number of observations in the Validation set for each fold = forecast period
      If None, a single fold is used
      :type cv Optional[int]
  
      :rtype object
      """
      self.original_target_col = target_col
      self.original_preds = [
          x for x in list(ts_df) if x not in [self.original_target_col]
      ]
  
      ts_df = ts_df[[self.original_target_col] + self.original_preds]
  
      #######################################
      #### Cross Validation across Folds ####
      #######################################
  
      rmse_folds = []
      norm_rmse_folds = []
      forecast_df_folds = []
      norm_rmse_folds2 = []
  
      ### Creating a new way to skip cross validation when trying to run auto-ts multiple times. ###
      if not cv:
          cv_in = 0
      else:
          cv_in = copy.deepcopy(cv)
      NFOLDS = self.get_num_folds_from_cv(cv)
      # cv = GapWalkForward(n_splits=NFOLDS, gap_size=0, test_size=self.forecast_period)
      # cv = TimeSeriesSplit(n_splits=NFOLDS, test_size=self.forecast_period) ### sklearn version 0.0.24
      max_trainsize = len(ts_df) - self.forecast_period
      try:
          cv = TimeSeriesSplit(
              n_splits=NFOLDS, test_size=self.forecast_period
          )  ### this works only sklearn v 0.0.24]
      except:
          cv = TimeSeriesSplit(
              n_splits=NFOLDS, max_train_size=max_trainsize
          )
  
      if type(ts_df) == dask.dataframe.core.DataFrame:
          ts_df = dft.head(
              len(ts_df)
          )  ### this converts dask into a pandas dataframe
  
      if cv_in == 0:
          print(
              "Skipping cross validation steps since cross_validation = %s"
              % cv_in
          )
          self.find_best_parameters(data=ts_df)
          y_train = ts_df.iloc[:, [0, self.best_d]]
          bestmodel = self.get_best_model(y_train)
          self.model = bestmodel.fit(disp=False)
      else:
          for fold_number, (train_index, test_index) in enumerate(
              cv.split(ts_df)
          ):
              dftx = ts_df.head(len(train_index) + len(test_index))
              ts_train = dftx.head(
                  len(train_index)
              )  ## now train will be the first segment of dftx
              ts_test = dftx.tail(
                  len(test_index)
              )  ### now test will be right after train in dftx
  
              print(
                  f"\nFold Number: {fold_number+1} --> Train Shape: {ts_train.shape[0]} Test Shape: {ts_test.shape[0]}"
              )
              self.find_best_parameters(data=ts_train)
  
              #########################################
              #### Define the model with fold data ####
              #########################################
              y_train = ts_train.iloc[:, [0, self.best_d]]
              bestmodel = self.get_best_model(y_train)
  
              ######################################
              #### Fit the model with fold data ####
              ######################################
  
              if self.verbose >= 1:
                  print(
                      f"Fitting best VAR model on Fold: {fold_number+1}"
                  )
              try:
                  self.model = bestmodel.fit(disp=False)
              except Exception as e:
                  print(e)
                  print(
                      f"Error: VAR Fit on Fold: {fold_number+1} unsuccessful."
                  )
                  return bestmodel, None, np.inf, np.inf
  
              forecast_df = self.predict(ts_test.shape[0], simple=False)
              forecast_df_folds.append(forecast_df["yhat"].values)
  
              rmse, norm_rmse = print_dynamic_rmse(
                  ts_test.iloc[:, 0].values,
                  forecast_df["yhat"].values,
                  ts_train.iloc[:, 0].values,
              )
              rmse_folds.append(rmse)
              norm_rmse_folds.append(norm_rmse)
  
          norm_rmse_folds2 = (
              rmse_folds / ts_df[self.original_target_col].values.std()
          )  # Same as what was there in print_dynamic_rmse()
          self.model.plot_diagnostics(figsize=(16, 12))
          axis = self.model.impulse_responses(
              12, orthogonalized=True
          ).plot(figsize=(12, 4))
          axis.set(
              xlabel="Time Steps",
              title="VAR model Impulse Response Functions",
          )
  
      ###############################################
      #### Refit the model on the entire dataset ####
      ###############################################
      y_train = ts_df.iloc[:, [0, self.best_d]]
      self.refit(ts_df=y_train)
  
      # return self.model, forecast_df_folds, rmse_folds, norm_rmse_folds
      return self.model, forecast_df_folds, rmse_folds, norm_rmse_folds2
  
imports: import pdb
  from typing import Optional
  import warnings
  import itertools
  import operator
  import copy
  import numpy
  import pandas
  from pandas.core.generic import NDFrame
  import dask
  import dask.dataframe
  import matplotlib.pyplot
  import seaborn
  from statsmodels.tsa.statespace.varmax import VARMAX
  from sklearn.model_selection import TimeSeriesSplit
  from ...utils import print_dynamic_rmse
  from ...models.ar_based.param_finder import find_lowest_pq
  from ..build_base import BuildBase
label_desc: Use image node_id 2 for calling the BuildVAR obj's underlying member method code with example usage: obj.fit(ts_df, target_col, cv) and returns: self,  forecast_df_folds,  rmse_folds,  norm_rmse_folds2, bestmodel,  None,  np,  np