class_docstr: Extend ReduceMixin to identify checks that output result per feature.
  
  Should implement the feature_reduce function and all the aggregation methods it supports.
docstr: Return an aggregated drift score based on aggregation method defined.
docstr_tok: ["Return","an","aggregated","drift","score","based","on","aggregation","method","defined","."]
code: def feature_reduce(
      aggregation_method: str,
      value_per_feature: pd.Series,
      feature_importance: Optional[pd.Series],
      score_name: str,
  ) -> Dict[str, float]:
      """Return an aggregated drift score based on aggregation method defined."""
      if aggregation_method is None or aggregation_method == "none":
          return dict(value_per_feature)
      elif aggregation_method == "mean":
          return {str("Mean " + score_name): np.mean(value_per_feature)}
      elif aggregation_method == "max":
          return {str("Max " + score_name): np.max(value_per_feature)}
  
      if aggregation_method not in [
          "weighted",
          "l3_weighted",
          "l5_weighted",
      ]:
          raise DeepchecksValueError(
              f"Unknown aggregation method: {aggregation_method}"
          )
      elif (
          feature_importance is None
          or feature_importance.isna().values.any()
      ):
          get_logger().warning(
              "Failed to calculate feature importance, using uniform mean instead."
          )
          return {
              str(
                  str.title(aggregation_method.replace("_", " "))
                  + " "
                  + score_name
              ): np.mean(value_per_feature)
          }
      else:
          value_per_feature = value_per_feature[
              feature_importance.index
          ]
          feature_importance = feature_importance[
              value_per_feature.notna().values
          ]
          value_per_feature.dropna(inplace=True)
          value_per_feature, feature_importance = np.asarray(
              value_per_feature
          ), np.asarray(feature_importance)
  
      if aggregation_method == "weighted":
          return {
              str("Weighted " + score_name): np.sum(
                  value_per_feature * feature_importance
              )
          }
      elif aggregation_method == "l3_weighted":
          return {
              str("L3 Weighted " + score_name): np.sum(
                  (value_per_feature**3) * feature_importance
              )
              ** (1.0 / 3)
          }
      elif aggregation_method == "l5_weighted":
          return {
              str("L5 Weighted " + score_name): np.sum(
                  (value_per_feature**5) * feature_importance
              )
              ** (1.0 / 5)
          }
  
imports: import abc
  from typing import Dict, Optional
  import numpy
  import pandas
  from deepchecks.core.errors import DeepchecksValueError
  from deepchecks.utils.logger import get_logger
label_desc: Use image node_id 2 for calling the ReduceFeatureMixin obj's underlying member method code with example usage: obj.feature_reduce(aggregation_method, value_per_feature, feature_importance, score_name) and returns: dict, dict, dict, dict, dict, dict, dict