code: def render_categorical(config: Settings, summary: dict) -> dict:
      varid = summary["varid"]
      n_obs_cat = config.vars.cat.n_obs
      image_format = config.plot.image_format
      words = config.vars.cat.words
      characters = config.vars.cat.characters
      length = config.vars.cat.length
  
      template_variables = render_common(config, summary)
  
      type_name = summary["type"]
      if isinstance(type_name, list):
          type_name = type_name[0]
  
      info = VariableInfo(
          summary["varid"],
          summary["varname"],
          type_name,
          summary["alerts"],
          summary["description"],
          style=config.html.style,
      )
  
      table = Table(
          [
              {
                  "name": "Distinct",
                  "value": fmt(summary["n_distinct"]),
                  "alert": "n_distinct" in summary["alert_fields"],
              },
              {
                  "name": "Distinct (%)",
                  "value": fmt_percent(summary["p_distinct"]),
                  "alert": "p_distinct" in summary["alert_fields"],
              },
              {
                  "name": "Missing",
                  "value": fmt(summary["n_missing"]),
                  "alert": "n_missing" in summary["alert_fields"],
              },
              {
                  "name": "Missing (%)",
                  "value": fmt_percent(summary["p_missing"]),
                  "alert": "p_missing" in summary["alert_fields"],
              },
              {
                  "name": "Memory size",
                  "value": fmt_bytesize(summary["memory_size"]),
                  "alert": False,
              },
          ],
          style=config.html.style,
      )
  
      fqm = FrequencyTableSmall(
          freq_table(
              freqtable=summary["value_counts_without_nan"],
              n=summary["count"],
              max_number_to_print=n_obs_cat,
          ),
          redact=config.vars.cat.redact,
      )
  
      template_variables["top"] = Container(
          [info, table, fqm], sequence_type="grid"
      )
  
      # ============================================================================================
  
      frequency_table = FrequencyTable(
          template_variables["freq_table_rows"],
          name="Common Values",
          anchor_id=f"{varid}common_values",
          redact=config.vars.cat.redact,
      )
  
      unique_stats = render_categorical_frequency(
          config, summary, varid
      )
  
      overview_items = []
  
      # length isn't being computed for categorical in spark
      if length and "max_length" in summary:
          length_table, length_histo = render_categorical_length(
              config, summary, varid
          )
          overview_items.append(length_table)
  
      # characters isn't being computed for categorical in spark
      if characters and "category_alias_counts" in summary:
          overview_table_char, unitab = render_categorical_unicode(
              config, summary, varid
          )
          overview_items.append(overview_table_char)
  
      overview_items.append(unique_stats)
  
      if not config.vars.cat.redact:
          rows = ("1st row", "2nd row", "3rd row", "4th row", "5th row")
  
          if isinstance(summary["first_rows"], list):
              sample = Table(
                  [
                      {
                          "name": name,
                          "value": fmt(value),
                          "alert": False,
                      }
                      for name, *value in zip(
                          rows, *summary["first_rows"]
                      )
                  ],
                  name="Sample",
                  style=config.html.style,
              )
          else:
              sample = Table(
                  [
                      {
                          "name": name,
                          "value": fmt(value),
                          "alert": False,
                      }
                      for name, value in zip(
                          rows, summary["first_rows"]
                      )
                  ],
                  name="Sample",
                  style=config.html.style,
              )
          overview_items.append(sample)
  
      # length isn't being computed in spark. disable rendering
      string_items: List[Renderable] = [frequency_table]
      if length and "max_length" in summary:
          string_items.append(length_histo)
  
      show = config.plot.cat_freq.show
      max_unique = config.plot.cat_freq.max_unique
  
      if show and (max_unique > 0):
          if isinstance(summary["value_counts_without_nan"], list):
              string_items.append(
                  Container(
                      [
                          Image(
                              cat_frequency_plot(
                                  config,
                                  s,
                              ),
                              image_format=image_format,
                              alt=config.html.style._labels[idx],
                              name=config.html.style._labels[idx],
                              anchor_id=f"{varid}cat_frequency_plot_{idx}",
                          )
                          if summary["n_distinct"][idx] <= max_unique
                          else HTML(
                              f"<h4 class='indent'>{config.html.style._labels[idx]}</h4><br />"
                              f"<em>Number of variable categories passes threshold (<code>config.plot.cat_freq.max_unique</code>)</em>"
                          )
                          for idx, s in enumerate(
                              summary["value_counts_without_nan"]
                          )
                      ],
                      anchor_id=f"{varid}cat_frequency_plot",
                      name="Common Values (Plot)",
                      sequence_type="batch_grid",
                      batch_size=len(config.html.style._labels),
                  )
              )
          elif (
              len(config.html.style._labels) == 1
              and summary["n_distinct"] <= max_unique
          ):
              string_items.append(
                  Image(
                      cat_frequency_plot(
                          config,
                          summary["value_counts_without_nan"],
                      ),
                      image_format=image_format,
                      alt="Common Values (Plot)",
                      name="Common Values (Plot)",
                      anchor_id=f"{varid}cat_frequency_plot",
                  )
              )
  
      bottom_items = [
          Container(
              overview_items,
              name="Overview",
              anchor_id=f"{varid}overview",
              sequence_type="batch_grid",
              batch_size=len(overview_items),
              titles=False,
          ),
          Container(
              string_items,
              name="Categories",
              anchor_id=f"{varid}string",
              sequence_type="named_list"
              if len(config.html.style._labels) > 1
              else "batch_grid",
              batch_size=len(config.html.style._labels),
          ),
      ]
  
      # words aren't being computed for categorical in spark
      if words and "word_counts" in summary:
          woc = freq_table(
              freqtable=summary["word_counts"],
              n=_get_n(summary["word_counts"]),
              max_number_to_print=10,
          )
  
          fqwo = FrequencyTable(
              woc,
              name="Common words",
              anchor_id=f"{varid}cwo",
              redact=config.vars.cat.redact,
          )
  
          bottom_items.append(
              Container(
                  [fqwo],
                  name="Words",
                  anchor_id=f"{varid}word",
                  sequence_type="grid",
              )
          )
  
      # characters aren't being computed for categorical in spark
      if characters and "category_alias_counts" in summary:
          bottom_items.append(
              Container(
                  [unitab],
                  name="Characters",
                  anchor_id=f"{varid}characters",
                  sequence_type="grid",
              )
          )
  
      # Bottom
      template_variables["bottom"] = Container(
          bottom_items, sequence_type="tabs", anchor_id=f"{varid}bottom"
      )
  
      return template_variables
  
file_path: ydata-profiling/src/ydata_profiling/report/structure/variables/render_categorical.py
imports: from typing import List, Tuple, Union
  import pandas
  from ydata_profiling.config import Settings
  from ydata_profiling.report.formatters import fmt, fmt_bytesize, fmt_number, fmt_numeric, fmt_percent, help
  from ydata_profiling.report.presentation.core import HTML, Container, FrequencyTable, FrequencyTableSmall, Image, Table, VariableInfo
  from ydata_profiling.report.presentation.core.renderable import Renderable
  from ydata_profiling.report.presentation.frequency_table_utils import freq_table
  from ydata_profiling.report.structure.variables.render_common import render_common
  from ydata_profiling.visualisation.plot import cat_frequency_plot, histogram
label_desc: Use image node_id 5 for calling a global function with example usage: render_categorical(config, summary) and returns: template_variables