class_docstr: SmartPlotter is a Bridge pattern decoupling plotting functions from SmartExplainer.
  The smartplotter class includes all the methods used to display graphics
  Each SmartPlotter method is easy to use from a Smart explainer object,
  just use the following syntax
  Attributes :
  explainer: object
      SmartExplainer instance to point to.
  Example
  --------
  >>> xpl.plot.my_plot_method(param=value)
class_docstr_tok: ["SmartPlotter","is","a","Bridge","pattern","decoupling","plotting","functions","from","SmartExplainer",".","The","smartplotter","class","includes","all","the","methods","used","to","display","graphics","Each","SmartPlotter","method","is","easy","to","use","from","a","Smart","explainer","object",",","just","use","the","following","syntax","Attributes",":","explainer",":","object","SmartExplainer","instance","to","point","to",".","Example","--","--","--","--",">",">",">","xpl.plot.my_plot_method","(","param=value",")"]
docstr: features_importance display a plotly features importance plot.
  in Multiclass Case, this features_importance focus on a label value.
  User specifies the label value using label parameter.
  the selection parameter allows the user to compare a subset to the global features
  importance
  features_importance tutorial offers several examples
   (please check tutorial part of this doc)
  Parameters
  ----------
  max_features: int (optional, default 20)
      this argument limit the number of hbar in features importance plot
      if max_features is 20, plot selects the 20 most important features
  selection: list (optional, default None)
      This argument allows to represent the importance calculated with a subset.
      Subset features importance is compared to global in the plot
      Argument must contains list of index, subset of the input DataFrame that we want to plot
  label: integer or string (default -1)
      If the label is of string type, check if it can be changed to integer to select the
      good dataframe object.
  group_name : str (optional, default None)
      Allows to display the features importance of the variables that are grouped together
      inside a group of features.
      This parameter is only available if the SmartExplainer object has been compiled using
      the features_groups optional parameter and should correspond to a key of
      features_groups dictionary.
  display_groups : bool (default True)
      If groups of features are declared in SmartExplainer object, this parameter allows to
      specify whether or not to display them.
  force: bool (optional, default False)
      force == True, force the compute features importance if it's already done
  width : Int (default: 900)
      Plotly figure - layout width
  height : Int (default: 500)
      Plotly figure - layout height
  file_name: string (optional)
      File name to use to save the plotly bar chart. If None the bar chart will not be saved.
  auto_open: Boolean (optional)
      Indicate whether to open the bar plot or not.
  zoom: bool (default=False)
      graph is currently zoomed
  Returns
  -------
  Plotly Figure Object
  Example
  --------
  >>> xpl.plot.features_importance()
code: def features_importance(
      self,
      max_features=20,
      selection=None,
      label=-1,
      group_name=None,
      display_groups=True,
      force=False,
      width=900,
      height=500,
      file_name=None,
      auto_open=False,
      zoom=False,
  ):
      """
      features_importance display a plotly features importance plot.
      in Multiclass Case, this features_importance focus on a label value.
      User specifies the label value using label parameter.
      the selection parameter allows the user to compare a subset to the global features
      importance
      features_importance tutorial offers several examples
       (please check tutorial part of this doc)
      Parameters
      ----------
      max_features: int (optional, default 20)
          this argument limit the number of hbar in features importance plot
          if max_features is 20, plot selects the 20 most important features
      selection: list (optional, default None)
          This argument allows to represent the importance calculated with a subset.
          Subset features importance is compared to global in the plot
          Argument must contains list of index, subset of the input DataFrame that we want to plot
      label: integer or string (default -1)
          If the label is of string type, check if it can be changed to integer to select the
          good dataframe object.
      group_name : str (optional, default None)
          Allows to display the features importance of the variables that are grouped together
          inside a group of features.
          This parameter is only available if the SmartExplainer object has been compiled using
          the features_groups optional parameter and should correspond to a key of
          features_groups dictionary.
      display_groups : bool (default True)
          If groups of features are declared in SmartExplainer object, this parameter allows to
          specify whether or not to display them.
      force: bool (optional, default False)
          force == True, force the compute features importance if it's already done
      width : Int (default: 900)
          Plotly figure - layout width
      height : Int (default: 500)
          Plotly figure - layout height
      file_name: string (optional)
          File name to use to save the plotly bar chart. If None the bar chart will not be saved.
      auto_open: Boolean (optional)
          Indicate whether to open the bar plot or not.
      zoom: bool (default=False)
          graph is currently zoomed
      Returns
      -------
      Plotly Figure Object
      Example
      --------
      >>> xpl.plot.features_importance()
      """
      self.explainer.compute_features_import(force=force)
      subtitle = None
      title = "Features Importance"
      display_groups = (
          self.explainer.features_groups is not None and display_groups
      )
      if display_groups:
          if (
              group_name
          ):  # Case where we have groups of features and we want to display only features inside a group
              if (
                  group_name
                  not in self.explainer.features_groups.keys()
              ):
                  raise ValueError(
                      f"group_name parameter : {group_name} is not in features_groups keys. "
                      f"Possible values are : {list(self.explainer.features_groups.keys())}"
                  )
              title += f" - {truncate_str(self.explainer.features_dict.get(group_name), 20)}"
              if isinstance(self.explainer.features_imp, list):
                  features_importance = [
                      label_feat_imp.loc[
                          label_feat_imp.index.isin(
                              self.explainer.features_groups[group_name]
                          )
                      ]
                      for label_feat_imp in self.explainer.features_imp
                  ]
              else:
                  features_importance = self.explainer.features_imp.loc[
                      self.explainer.features_imp.index.isin(
                          self.explainer.features_groups[group_name]
                      )
                  ]
              contributions = self.explainer.contributions
          else:
              features_importance = self.explainer.features_imp_groups
              contributions = self.explainer.contributions_groups
      else:
          features_importance = self.explainer.features_imp
          contributions = self.explainer.contributions
  
      # classification
      if self.explainer._case == "classification":
          label_num, _, label_value = self.explainer.check_label_name(
              label
          )
          global_feat_imp = features_importance[label_num].tail(
              max_features
          )
          if selection is not None:
              subset_feat_imp = (
                  self.explainer.backend.get_global_features_importance(
                      contributions=contributions[label_num],
                      explain_data=self.explainer.explain_data,
                      subset=selection,
                  )
              )
          else:
              subset_feat_imp = None
          subtitle = f"Response: <b>{label_value}</b>"
      # regression
      elif self.explainer._case == "regression":
          global_feat_imp = features_importance.tail(max_features)
          if selection is not None:
              subset_feat_imp = (
                  self.explainer.backend.get_global_features_importance(
                      contributions=contributions,
                      explain_data=self.explainer.explain_data,
                      subset=selection,
                  )
              )
          else:
              subset_feat_imp = None
      addnote = ""
      if subset_feat_imp is not None:
          subset_feat_imp = subset_feat_imp.reindex(
              global_feat_imp.index
          )
          subset_feat_imp.index = subset_feat_imp.index.map(
              self.explainer.features_dict
          )
          if subset_feat_imp.dropna().shape[0] == 0:
              raise ValueError(
                  "selection argument doesn't return any row"
              )
          subset_len = len(selection)
          total_len = self.explainer.x_init.shape[0]
          addnote = add_text(
              [
                  addnote,
                  f"Subset length: {subset_len} ({int(np.round(100 * subset_len / total_len))}%)",
              ],
              sep=" - ",
          )
      if self.explainer.x_init.shape[1] >= max_features:
          addnote = add_text(
              [
                  addnote,
                  f"Total number of features: {int(self.explainer.x_init.shape[1])}",
              ],
              sep=" - ",
          )
  
      global_feat_imp.index = global_feat_imp.index.map(
          self.explainer.features_dict
      )
      if display_groups:
          # Bold font for groups of features
          global_feat_imp.index = [
              "<b>" + str(f)
              if self.explainer.inv_features_dict.get(f)
              in self.explainer.features_groups.keys()
              else str(f)
              for f in global_feat_imp.index
          ]
          if subset_feat_imp is not None:
              subset_feat_imp.index = [
                  "<b>" + str(f)
                  if self.explainer.inv_features_dict.get(f)
                  in self.explainer.features_groups.keys()
                  else str(f)
                  for f in subset_feat_imp.index
              ]
  
      fig = self.plot_features_import(
          global_feat_imp,
          subset_feat_imp,
          title,
          addnote,
          subtitle,
          width,
          height,
          file_name,
          auto_open,
          zoom,
      )
      return fig
  
imports: import warnings
  from numbers import Number
  import random
  import copy
  import math
  import numpy
  from scipy.optimize import fsolve
  import scipy.cluster.hierarchy
  import pandas
  from plotly import graph_objs
  import plotly.express
  from plotly.subplots import make_subplots
  from plotly.offline import plot
  from shapash.manipulation.select_lines import select_lines
  from shapash.manipulation.summarize import compute_features_import, project_feature_values_1d, compute_corr
  from shapash.utils.utils import add_line_break, truncate_str, compute_digit_number, add_text, maximum_difference_sort_value, compute_sorted_variables_interactions_list_indices, compute_top_correlations_features
  from shapash.webapp.utils.utils import round_to_k
  from shapash.style.style_utils import colors_loading, select_palette, define_style
label_desc: Use image node_id 16 for calling the SmartPlotter obj's underlying member method code with example usage: obj.features_importance(max_features, selection, label, group_name, display_groups, force, width, height, file_name, auto_open, zoom) and returns: fig