code: def assign_bins(
      x,
      breaks: FloatArrayLike,
      weight: Optional[FloatArrayLike] = None,
      pad: bool = False,
      closed: Literal["right", "left"] = "right",
  ):
      """
      Assign value in x to bins demacated by the break points
  
      Parameters
      ----------
      x :
          Values to be binned.
      breaks :
          Sequence of break points.
      weight :
          Weight of each value in `x`. Used in creating the frequency
          table. If `None`, then each value in `x` has a weight of 1.
      pad :
          If `True`, add empty bins at either end of `x`.
      closed :
          Whether the right or left edges of the bins are part of the
          bin.
  
      Returns
      -------
      out : dataframe
          Bin count and density information.
      """
      right = closed == "right"
      # If weight not supplied to, use one (no weight)
      if weight is None:
          weight = np.ones(len(x))
      else:
          weight = np.asarray(weight)
          weight[np.isnan(weight)] = 0
  
      bin_idx = pd.cut(
          x,
          bins=breaks,  # type: ignore
          labels=False,
          right=right,
          include_lowest=True,
      )
      bin_widths = np.diff(breaks)
      bin_x = (breaks[:-1] + breaks[1:]) * 0.5  # type: ignore
  
      # Create a dataframe with two columns:
      #   - the bins to which each x is assigned
      #   - the weight of each x value
      # Then create a weighted frequency table
      bins_long = pd.DataFrame({"bin_idx": bin_idx, "weight": weight})
      wftable = bins_long.pivot_table(
          "weight", index=["bin_idx"], aggfunc="sum"
      )["weight"]
  
      # Empty bins get no value in the computed frequency table.
      # We need to add the zeros and since frequency table is a
      # Series object, we need to keep it ordered
      if len(wftable) < len(bin_x):
          empty_bins = set(range(len(bin_x))) - set(bin_idx)
          for b in empty_bins:
              wftable.loc[b] = 0  # pyright: ignore
          wftable = wftable.sort_index()
      bin_count = wftable.tolist()
  
      if pad:
          bw0 = bin_widths[0]
          bwn = bin_widths[-1]
          bin_count = np.hstack([0, bin_count, 0])
          bin_widths = np.hstack([bw0, bin_widths, bwn])
          bin_x = np.hstack([bin_x[0] - bw0, bin_x, bin_x[-1] + bwn])
  
      return result_dataframe(bin_count, bin_x, bin_widths)
  
file_path: plotnine/plotnine/stats/binning.py
imports: from __future__ import annotations
  import typing
  import numpy
  import pandas
  from ..exceptions import PlotnineError
  from ..scales.scale_discrete import scale_discrete
label_desc: Use image node_id 4 for calling a global function with example usage: assign_bins(x, breaks, weight, pad, closed) and returns: result_dataframe