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 setup_data(self, data: pd.DataFrame) -> pd.DataFrame:
      gp = self.params
      sp = self._stat.params
  
      # Issue warnings when parameters don't make sense
      if gp["position"] == "stack":
          warn(
              "position='stack' doesn't work properly with "
              "geom_dotplot. Use stackgroups=True instead.",
              PlotnineWarning,
          )
      if (
          gp["stackgroups"]
          and sp["method"] == "dotdensity"
          and sp["binpositions"] == "bygroup"
      ):
          warn(
              "geom_dotplot called with stackgroups=TRUE and "
              "method='dotdensity'. You probably want to set "
              "binpositions='all'",
              PlotnineWarning,
          )
  
      if "width" not in data:
          if sp["width"]:
              data["width"] = sp["width"]
          else:
              data["width"] = resolution(data["x"], False) * 0.9
  
      # Set up the stacking function and range
      if gp["stackdir"] in (None, "up"):
  
          def stackdots(a: FloatSeries) -> FloatSeries:
              return a - 0.5
  
          stackaxismin: float = 0
          stackaxismax: float = 1
      elif gp["stackdir"] == "down":
  
          def stackdots(a: FloatSeries) -> FloatSeries:
              return -a + 0.5
  
          stackaxismin = -1
          stackaxismax = 0
      elif gp["stackdir"] == "center":
  
          def stackdots(a: FloatSeries) -> FloatSeries:
              return a - 1 - np.max(a - 1) / 2
  
          stackaxismin = -0.5
          stackaxismax = 0.5
      elif gp["stackdir"] == "centerwhole":
  
          def stackdots(a: FloatSeries) -> FloatSeries:
              return a - 1 - np.floor(np.max(a - 1) / 2)
  
          stackaxismin = -0.5
          stackaxismax = 0.5
      else:
          raise ValueError(f"Invalid value stackdir={gp['stackdir']}")
  
      # Fill the bins: at a given x (or y),
      # if count=3, make 3 entries at that x
      idx = [
          i for i, c in enumerate(data["count"]) for j in range(int(c))
      ]
      data = data.iloc[idx]
      data.reset_index(inplace=True, drop=True)
      # Next part will set the position of each dot within each stack
      # If stackgroups=TRUE, split only on x (or y) and panel;
      # if not stacking, also split by group
      groupvars = [sp["binaxis"], "PANEL"]
      if not gp["stackgroups"]:
          groupvars.append("group")
  
      # Within each x, or x+group, set countidx=1,2,3,
      # and set stackpos according to stack function
      def func(df: pd.DataFrame) -> pd.DataFrame:
          df["countidx"] = range(1, len(df) + 1)
          df["stackpos"] = stackdots(df["countidx"])
          return df
  
      # Within each x, or x+group, set countidx=1,2,3, and set
      # stackpos according to stack function
      data = groupby_apply(data, groupvars, func)
  
      # Set the bounding boxes for the dots
      if sp["binaxis"] == "x":
          # ymin, ymax, xmin, and xmax define the bounding
          # rectangle for each stack. Can't do bounding box per dot,
          # because y position isn't real.
          # After position code is rewritten, each dot should have
          # its own bounding box.
          data["xmin"] = data["x"] - data["binwidth"] / 2
          data["xmax"] = data["x"] + data["binwidth"] / 2
          data["ymin"] = stackaxismin
          data["ymax"] = stackaxismax
          data["y"] = 0
      elif sp["binaxis"] == "y":
          # ymin, ymax, xmin, and xmax define the bounding
          # rectangle for each stack. Can't do bounding box per dot,
          # because x position isn't real.
          # xmin and xmax aren't really the x bounds. They're just
          # set to the standard x +- width/2 so that dot clusters
          # can be dodged like other geoms.
          # After position code is rewritten, each dot should have
          # its own bounding box.
          def func(df: pd.DataFrame) -> pd.DataFrame:
              df["ymin"] = df["y"].min() - data["binwidth"][0] / 2
              df["ymax"] = df["y"].max() + data["binwidth"][0] / 2
              return df
  
          data = groupby_apply(data, "group", func)
          data["xmin"] = data["x"] + data["width"] * stackaxismin
          data["xmax"] = data["x"] + data["width"] * stackaxismax
  
      return data
  
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 1 for calling the geom_dotplot obj's underlying member method code with example usage: obj.setup_data(data) and returns: data, df, unknown, unknown, df, unknown, unknown