code: def merge_features(
      df, df_user, df_item, sparse_features, dense_features
  ):
      sparse_feats_input_dims = []
      for i in sparse_features:
          if i in df_user.columns:
              df_user, embed_dim = string_index(df_user, i)
          else:
              df_item, embed_dim = string_index(df_item, i)
          sparse_feats_input_dims.append(embed_dim)
      for i in dense_features:
          if i in df_user.columns:
              df_user = min_max_scale(df_user, i)
          else:
              df_item = min_max_scale(df_item, i)
      df_feat = df.join(df_user, "user", "inner")
      df_feat = df_feat.join(df_item, "item", "inner")
      return df_feat, sparse_feats_input_dims
  
file_path: BigDL/python/orca/tutorial/NCF/process_spark_dataframe.py
imports: import os
  from pyspark.ml.feature import StringIndexer, MinMaxScaler, VectorAssembler
  from pyspark.ml import Pipeline
  from pyspark.sql.types import StructField, StructType, IntegerType, LongType, ArrayType, StringType
  from pyspark.sql.functions import udf, lit, collect_list, explode, concat
  from bigdl.orca import OrcaContext
label_desc: Use image node_id 5 for calling a global function with example usage: merge_features(df, df_user, df_item, sparse_features, dense_features) and returns: df_feat,  sparse_feats_input_dims