class_docstr: Class which contains methods for data preprocessing.
  The class performs two types of preprocessing: obligatory and optional.
  
  obligatory - deletes rows where nans in the target, removes features,
      which full of nans, deletes extra_spaces
  optional - depends on what operations are in the pipeline, gap-filling
      is applied if there is no imputation operation in the pipeline, categorical
      encoding is applied if there is no encoder in the structure of the pipeline etc.
class_docstr_tok: ["Class","which","contains","methods","for","data","preprocessing",".","The","class","performs","two","types","of","preprocessing",":","obligatory","and","optional",".","obligatory","-","deletes","rows","where","nans","in","the","target",",","removes","features",",","which","full","of","nans",",","deletes","extra_spaces","optional","-","depends","on","what","operations","are","in","the","pipeline",",","gap-filling","is","applied","if","there","is","no","imputation","operation","in","the","pipeline",",","categorical","encoding","is","applied","if","there","is","no","encoder","in","the","structure","of","the","pipeline","etc","."]
docstr: Finds features with less than ALLOWED_NAN_PERCENT of nan's
  
  Args:
      data: data to find columns with nan values
      source_name: name of the data source node
docstr_tok: ["Finds","features","with","less","than","ALLOWED_NAN_PERCENT","of","nan's","Args",":","data",":","data","to","find","columns","with","nan","values","source_name",":","name","of","the","data","source","node"]
code: def _find_features_lacking_nans(
      self, data: InputData, source_name: str
  ):
      """
      Finds features with less than ALLOWED_NAN_PERCENT of nan's
  
      Args:
          data: data to find columns with nan values
          source_name: name of the data source node
      """
      features = data.features
      axes_except_cols = (0,) + tuple(range(2, features.ndim))
      are_allowed = (
          np.mean(pd.isna(features), axis=axes_except_cols)
          < ALLOWED_NAN_PERCENT
      )
      self.ids_relevant_features[source_name] = np.flatnonzero(
          are_allowed
      )
  
imports: from copy import copy
  from typing import Optional, Union
  import numpy
  import pandas
  from golem.core.log import default_log
  from golem.core.paths import copy_doc
  from sklearn.preprocessing import LabelEncoder
  from fedot.core.data.data import InputData, np_datetime_to_numeric
  from fedot.core.data.data import OutputData, data_type_is_table, data_type_is_text, data_type_is_ts
  from fedot.core.data.data_preprocessing import data_has_categorical_features, data_has_missing_values, find_categorical_columns, replace_inf_with_nans, replace_nans_with_empty_strings
  from fedot.core.data.multi_modal import MultiModalData
  from fedot.core.operations.evaluation.operation_implementations.data_operations.categorical_encoders import LabelEncodingImplementation, OneHotEncodingImplementation
  from fedot.core.operations.evaluation.operation_implementations.data_operations.sklearn_transformations import ImputationImplementation
  from fedot.core.repository.dataset_types import DataTypesEnum
  from fedot.core.repository.tasks import TaskTypesEnum
  from fedot.preprocessing.base_preprocessing import BasePreprocessor
  from fedot.preprocessing.categorical import BinaryCategoricalPreprocessor
  from fedot.preprocessing.data_type_check import exclude_image, exclude_multi_ts, exclude_ts
  from fedot.preprocessing.data_types import TYPE_TO_ID, TableTypesCorrector
  from fedot.preprocessing.structure import DEFAULT_SOURCE_NAME, PipelineStructureExplorer
label_desc: Use image node_id 12 for calling the DataPreprocessor obj's underlying member method code with example usage: obj._find_features_lacking_nans(data, source_name) without return types