class_docstr: Dot plot
  
  {usage}
  
  Parameters
  ----------
  {common_parameters}
  stackdir : Literal["up", "down", "center", "centerwhole"], default="up"
      Direction in which to stack the dots. Options are
  stackratio : float, default=1
      How close to stack the dots. If value is less than 1,
      the dots overlap, if greater than 1 they are spaced.
  dotsize : float, default=1
      Diameter of dots relative to `binwidth`.
  stackgroups : bool, default=False
      If `True`{.py}, the dots are stacked across groups.
  
  See Also
  --------
  plotnine.stats.stat_bindot
class_docstr_tok: ["Dot","plot","{","usage","}","Parameters","--","--","--","--","--","{","common_parameters","}","stackdir",":","Literal","[","``","up","''",",","``","down","''",",","``","center","''",",","``","centerwhole","''","]",",","default=","''","up","''","Direction","in","which","to","stack","the","dots",".","Options","are","stackratio",":","float",",","default=1","How","close","to","stack","the","dots",".","If","value","is","less","than","1",",","the","dots","overlap",",","if","greater","than","1","they","are","spaced",".","dotsize",":","float",",","default=1","Diameter","of","dots","relative","to","`","binwidth","`",".","stackgroups",":","bool",",","default=False","If","`","True","`","{",".py","}",",","the","dots","are","stacked","across","groups",".","See","Also","--","--","--","--","plotnine.stats.stat_bindot"]
code: def draw_group(
      data: pd.DataFrame,
      panel_params: panel_view,
      coord: Coord,
      ax: Axes,
      **params: Any,
  ):
      from matplotlib.collections import PatchCollection
      from matplotlib.patches import Ellipse
  
      data = coord.transform(data, panel_params)
      fill = to_rgba(data["fill"], data["alpha"])
      color = to_rgba(data["color"], data["alpha"])
      ranges = coord.range(panel_params)
  
      # For perfect circles the width/height of the circle(ellipse)
      # should factor in the dimensions of axes
      bbox = ax.get_window_extent().transformed(
          ax.figure.dpi_scale_trans.inverted()  # pyright: ignore
      )
      ax_width, ax_height = bbox.width, bbox.height
  
      factor = (
          (ax_width / ax_height) * np.ptp(ranges.y) / np.ptp(ranges.x)
      )
      size = data.loc[0, "binwidth"] * params["dotsize"]
      offsets = data["stackpos"] * params["stackratio"]
  
      if params["binaxis"] == "x":
          width, height = size, size * factor
          xpos, ypos = data["x"], data["y"] + height * offsets
      elif params["binaxis"] == "y":
          width, height = size / factor, size
          xpos, ypos = data["x"] + width * offsets, data["y"]
      else:
          raise ValueError(
              f"Invalid valid value binaxis={params['binaxis']}"
          )
  
      circles = []
      for xy in zip(xpos, ypos):
          patch = Ellipse(xy, width=width, height=height)
          circles.append(patch)
  
      coll = PatchCollection(
          circles,
          edgecolors=color,
          facecolors=fill,
          rasterized=params["raster"],
      )
      ax.add_collection(coll)
  
file_path: plotnine/plotnine/geoms/geom_dotplot.py
imports: from __future__ import annotations
  import typing
  from warnings import warn
  import numpy
  from .._utils import groupby_apply, resolution, to_rgba
  from ..doctools import document
  from ..exceptions import PlotnineWarning
  from .geom import geom
label_desc: Use image node_id 2 for calling the geom_dotplot obj's underlying member method code with example usage: obj.draw_group(data, panel_params, coord, ax) without return types