code: def generate_fig_univariate_categorical(
      df_all: pd.DataFrame,
      col: str,
      hue: str,
      nb_cat_max: int = 7,
      colors_dict: Optional[dict] = None,
  ) -> plt.Figure:
      """
      Returns a matplotlib figure containing the distribution of a categorical feature.
  
      If the feature is categorical and contains too many categories, the smallest
      categories are grouped into a new 'Other' category so that the graph remains
      readable.
  
      Parameters
      ----------
      df_all : pd.DataFrame
          The input dataframe that contains the column of interest
      col : str
          The column of interest
      hue : str
          The column used to distinguish the values (ex. 'train' and 'test')
      nb_cat_max : int
          The number max of categories to be displayed. If the number of categories
          is greater than nb_cat_max then groups smallest categories into a new
          'Other' category
      colors_dict : dict
          dict of colors used
  
      Returns
      -------
      matplotlib.pyplot.Figure
      """
      colors_dict = colors_dict or get_palette("default")
      df_cat = (
          df_all.groupby([col, hue])
          .agg({col: "count"})
          .rename(columns={col: "count"})
          .reset_index()
      )
      df_cat["Percent"] = (
          df_cat["count"]
          * 100
          / df_cat.groupby(hue)["count"].transform("sum")
      )
  
      if pd.api.types.is_numeric_dtype(df_cat[col].dtype):
          df_cat = df_cat.sort_values(col, ascending=True)
          df_cat[col] = df_cat[col].astype(str)
  
      nb_cat = (
          df_cat.groupby([col])
          .agg({"count": "sum"})
          .reset_index()[col]
          .nunique()
      )
  
      if nb_cat > nb_cat_max:
          df_cat = _merge_small_categories(
              df_cat=df_cat, col=col, hue=hue, nb_cat_max=nb_cat_max
          )
  
      fig, ax = plt.subplots(figsize=(7, 4))
  
      sns.barplot(
          data=df_cat,
          x="Percent",
          y=col,
          hue=hue,
          palette=get_pyplot_color(
              colors=colors_dict["report_feature_distribution"]
          ),
          ax=ax,
      )
  
      for p in ax.patches:
          ax.annotate(
              "{:.1f}%".format(np.nan_to_num(p.get_width(), nan=0)),
              xy=(p.get_width(), p.get_y() + p.get_height() / 2),
              xytext=(5, 0),
              textcoords="offset points",
              ha="left",
              va="center",
          )
  
      # Shrink current axis by 20%
      box = ax.get_position()
      ax.set_position([box.x0, box.y0, box.width * 0.8, box.height])
  
      # Put a legend to the right of the current axis
      ax.legend(loc="center left", bbox_to_anchor=(1, 0.5))
  
      # Removes plot borders
      ax.spines["top"].set_visible(False)
      ax.spines["right"].set_visible(False)
  
      new_labels = [
          truncate_str(i.get_text(), maxlen=45)
          for i in ax.yaxis.get_ticklabels()
      ]
      ax.yaxis.set_ticklabels(new_labels)
  
      return fig
  
file_path: shapash/shapash/report/plots.py
imports: from typing import Union, Optional
  import pandas
  import numpy
  import seaborn
  import matplotlib.pyplot
  from matplotlib.colors import LinearSegmentedColormap
  from shapash.utils.utils import truncate_str
  from shapash.report.common import VarType
  from shapash.style.style_utils import get_pyplot_color, get_palette
label_desc: Use image node_id 3 for calling a global function with example usage: generate_fig_univariate_categorical(df_all, col, hue, nb_cat_max, colors_dict) and returns: fig