code: def concatenate_df(train_df, vali_df, test_df, backend):
      train_size = len(train_df)
      vali_size = len(vali_df) if vali_df is not None else 0
  
      concatenated_df = backend.df_engine.df_lib.concat(
          [df for df in [train_df, vali_df, test_df] if df is not None],
          ignore_index=True,
      )
  
      def get_split(idx):
          if idx < train_size:
              return 0
          if idx < train_size + vali_size:
              return 1
          return 2
  
      concatenated_df[SPLIT] = (
          concatenated_df.index.to_series()
          .map(get_split)
          .astype(np.int8)
      )
      return concatenated_df
  
file_path: ludwig/ludwig/data/concatenate_datasets.py
imports: import argparse
  import logging
  import numpy
  from ludwig.backend import LOCAL_BACKEND
  from ludwig.constants import SPLIT
  from ludwig.utils.data_utils import read_csv
label_desc: Use image node_id 3 for calling a global function with example usage: concatenate_df(train_df, vali_df, test_df, backend) and returns: concatenated_df, int, int, int