code: def feature_engineering(
      train_tbl,
      valid_tbl,
      output_path,
      sparse_int_features,
      sparse_string_features,
      dense_features,
  ):
      train_tbl, min_max_dict = train_tbl.min_max_scale(dense_features)
      valid_tbl = valid_tbl.transform_min_max_scale(
          dense_features, min_max_dict
      )
  
      cat_cols = sparse_string_features + sparse_int_features
      for feature in cat_cols:
          train_tbl, feature_idx = train_tbl.category_encode(feature)
          valid_tbl = valid_tbl.encode_string(feature, feature_idx)
          valid_tbl = valid_tbl.fillna(0, feature)
          print(
              "The class number of feature: {}/{}".format(
                  feature, feature_idx.size()
              )
          )
          feature_idx.write_parquet(
              os.path.join(output_path, "feature_maps")
          )
      return train_tbl, valid_tbl
  
file_path: BigDL/python/friesian/example/multi_task/data_processing.py
imports: import os
  from argparse import ArgumentParser
  from bigdl.dllib.utils.log4Error import invalidInputError
  from bigdl.orca import init_orca_context, stop_orca_context
  from bigdl.friesian.feature import FeatureTable
label_desc: Use image node_id 4 for calling a global function with example usage: feature_engineering(train_tbl, valid_tbl, output_path, sparse_int_features, sparse_string_features, dense_features) and returns: train_tbl,  valid_tbl