class_docstr: Base class for encoders that includes the code to categorize and
  transform the input features.
docstr: Perform custom check_array:
  - convert list of strings to object dtype
  - check for missing values for object dtype data (check_array does
    not do that)
  - return list of features (arrays): this list of features is
    constructed feature by feature to preserve the data types
    of pandas DataFrame columns, as otherwise information is lost
    and cannot be used, eg for the `categories_` attribute.
docstr_tok: ["Perform","custom","check_array",":","-","convert","list","of","strings","to","object","dtype","-","check","for","missing","values","for","object","dtype","data","(","check_array","does","not","do","that",")","-","return","list","of","features","(","arrays",")",":","this","list","of","features","is","constructed","feature","by","feature","to","preserve","the","data","types","of","pandas","DataFrame","columns",",","as","otherwise","information","is","lost","and","can","not","be","used",",","eg","for","the","`","categories_","`","attribute","."]
code: def _check_X(self, X):
      """
      Perform custom check_array:
      - convert list of strings to object dtype
      - check for missing values for object dtype data (check_array does
        not do that)
      - return list of features (arrays): this list of features is
        constructed feature by feature to preserve the data types
        of pandas DataFrame columns, as otherwise information is lost
        and cannot be used, eg for the `categories_` attribute.
  
      """
      if not (hasattr(X, "iloc") and getattr(X, "ndim", 0) == 2):
          # if not a dataframe, do normal check_array validation
          X_temp = check_array(X, dtype=None, force_all_finite=False)
          if not hasattr(X, "dtype") and np.issubdtype(
              X_temp.dtype, np.str_
          ):
              X = check_array(X, dtype=object)
          else:
              X = X_temp
          needs_validation = False
      else:
          # pandas dataframe, do validation later column by column, in order
          # to keep the dtype information to be used in the encoder.
          needs_validation = True
  
      n_samples, n_features = X.shape
      X_columns = []
  
      for i in range(n_features):
          Xi = self._get_feature(X, feature_idx=i)
          Xi = check_array(
              Xi,
              ensure_2d=False,
              dtype=None,
              force_all_finite=needs_validation,
          )
          X_columns.append(Xi)
  
      return X_columns, n_samples, n_features
  
imports: import copy
  from numbers import Integral
  import numpy
  from scipy import sparse
  from sklearn.base import BaseEstimator, TransformerMixin
  from sklearn.utils import check_array
  from sklearn.utils.validation import check_is_fitted
  from autogluon.features.generators import LabelEncoderFeatureGenerator
label_desc: Use image node_id 1 for calling the _BaseEncoder obj's underlying member method code with example usage: obj._check_X(X) and returns: X_columns,  n_samples,  n_features