code: def get_column_types(*, data, threshold, label=None):
      """
      Retrieve data with default data type, when metadata is not provided
  
      Args:
          data (pandas): sample data
          threshold (float): data threshold
          label (str, Optional): label column name
  
      Returns:
          feature, valid_feature_names, valid_feature_types, meta
      """
  
      def check_key(_data):
          if _data.dtypes in [np.int32, np.int64, np.int16]:
              if _data.is_monotonic:
                  return True
              else:
                  return False
          else:
              return False
  
      def check_numerical(_data):
          if _data.dtypes in [
              np.float64,
              np.float32,
              np.int16,
              np.int32,
              np.int64,
          ]:
              return True
          else:
              return False
  
      def check_datetime(_data):
          if _data.dtypes in [np.int16, np.int64, np.int32]:
              return False
  
          def parse_date(_date):
              try:
                  dateutil.parser.parse(str(_date))
                  return 0
              except ValueError:
                  return 1
              except OverflowError:
                  return 1
  
          counter = Counter(_data.tolist())
          if len(counter) >= threshold * len(_data):
              invalid_count = 0
              for date in _data.tolist():
                  invalid_count += parse_date(date)
              if invalid_count < threshold * len(_data):
                  return True
              else:
                  return False
          else:
              return False
  
      def check_categorical(_data):
          counter = Counter(
              [
                  str(x) if type(x) == float and math.isnan(x) else x
                  for x in _data.tolist()
              ]
          )
          if _data.dtypes in [np.float64, np.float32]:
              _threshold = min(
                  THRESHOLD.FLOAT_UNIQUE_ABS_THRESHOLD,
                  threshold * len(_data),
              )  ## for float type, strict the threshold
          elif _data.dtypes in [np.int16, np.int32, np.int64]:
              _threshold = min(
                  THRESHOLD.INT_UNIQUE_ABS_THRESHOLD,
                  threshold * len(_data),
              )  ## for int type, strict the threshold
          else:
              _threshold = threshold * len(_data)
          if len(counter) < _threshold:
              _median = median(counter.values())
              if _median == 1:
                  return False
              else:
                  return True
          else:
              return False
  
      def check_text(_data):
          if _data.dtypes != object:
              return False
  
          def _get_token_number(x):
              x = str(x)
              return len(x.split(" "))
  
          if len(_data.unique()) > len(_data) * threshold:
              if median(col_data.apply(_get_token_number)) >= 2:
                  return True
              else:
                  return False
          else:
              return False
  
      valid_feature_names = []
      valid_feature_types = []
      feature = dict()
      feature[DATATYPE.CATEGORY] = []
      feature[DATATYPE.NUMBER] = []
      feature[DATATYPE.FREETEXT] = []
      feature[DATATYPE.DATETIME] = []
      meta = {}
  
      for column in data.columns:
          if column == label:
              meta[column] = {
                  DATATYPE.TYPE: DATATYPE.LABEL,
                  DATATYPE.USED: True,
                  DATATYPE.STRUCTURED: DATATYPE.ATTRIBUTE,
              }
              continue
          col_data = data[column]
  
          if check_datetime(_data=col_data):
              # datetime data
              feature[DATATYPE.DATETIME].append(column)
              valid_feature_names.append(column)
              valid_feature_types.append(DATATYPE.DATETIME)
              meta[column] = {
                  DATATYPE.TYPE: DATATYPE.DATETIME,
                  DATATYPE.USED: True,
                  DATATYPE.STRUCTURED: DATATYPE.ATTRIBUTE,
              }
  
          elif check_categorical(_data=col_data):
              # categorical data
              feature[DATATYPE.CATEGORY].append(column)
              valid_feature_names.append(column)
              valid_feature_types.append(DATATYPE.CATEGORY)
              meta[column] = {
                  DATATYPE.TYPE: DATATYPE.CATEGORY,
                  DATATYPE.USED: True,
                  DATATYPE.STRUCTURED: DATATYPE.ATTRIBUTE,
              }
  
          elif check_key(_data=col_data):
              warnings.warn(
                  message="Warning: the feature [%s] is suspected to be key feature as it is monotonic integer. \n"
                  "[Examples]: %s\n" % (column, col_data.tolist()[:5])
              )
              meta[column] = {
                  DATATYPE.TYPE: DATATYPE.KEY,
                  DATATYPE.USED: False,
                  DATATYPE.STRUCTURED: DATATYPE.ATTRIBUTE,
              }
  
          elif check_numerical(_data=col_data):
              # numerical data
              feature[DATATYPE.NUMBER].append(column)
              valid_feature_names.append(column)
              valid_feature_types.append(DATATYPE.NUMBER)
              meta[column] = {
                  DATATYPE.TYPE: DATATYPE.NUMBER,
                  DATATYPE.USED: True,
                  DATATYPE.STRUCTURED: DATATYPE.ATTRIBUTE,
              }
          elif check_text(_data=col_data):
              # text data
              feature[DATATYPE.FREETEXT].append(column)
              valid_feature_names.append(column)
              valid_feature_types.append(DATATYPE.FREETEXT)
              meta[column] = {
                  DATATYPE.TYPE: DATATYPE.FREETEXT,
                  DATATYPE.USED: True,
                  DATATYPE.STRUCTURED: DATATYPE.ATTRIBUTE,
              }
  
          else:
              warnings.warn(
                  message="Warning: the feature [%s] is suspected to be identifiable feature. \n"
                  "[Examples]: %s\n" % (column, col_data.tolist()[:5])
              )
              meta[column] = {
                  DATATYPE.TYPE: DATATYPE.KEY,
                  DATATYPE.USED: False,
                  DATATYPE.STRUCTURED: DATATYPE.ATTRIBUTE,
              }
  
      return feature, valid_feature_names, valid_feature_types, meta
  
file_path: contextual-ai/xai/data/helper.py
imports: import json
  import warnings
  from collections import Counter
  from statistics import median
  import dateutil
  import numpy
  import math
  from xai.data.constants import DATATYPE, THRESHOLD
  from xai.data.explorer import CategoricalDataAnalyzer, DataAnalyzerSuite
  from xai.data.validator import MissingValidator
label_desc: Use image node_id 1 for calling a global function with example usage: get_column_types() and returns: feature,  valid_feature_names,  valid_feature_types,  meta, False, True, False, False, False, False, False, len, False, True, False, int, True, False, False, True, True, False, int, int