class_docstr: Box and whiskers plot
  
  {usage}
  
  Parameters
  ----------
  {common_parameters}
  width : float, default=None
      Box width. If `None`{.py}, the width is set to
      `90%` of the resolution of the data. Note that if the stat
      has a width parameter, that takes precedence over this one.
  outlier_alpha : float, default=1
      Transparency of the outlier points.
  outlier_color : str | tuple, default=None
      Color of the outlier points.
  outlier_shape : str, default="o"
      Shape of the outlier points. An empty string hides the outliers.
  outlier_size : float, default=1.5
      Size of the outlier points.
  outlier_stroke : float, default=0.5
      Stroke-size of the outlier points.
  notch : bool, default=False
      Whether the boxes should have a notch.
  varwidth : bool, default=False
      If `True`{.py}, boxes are drawn with widths proportional to
      the square-roots of the number of observations in the
      groups.
  notchwidth : float, default=0.5
      Width of notch relative to the body width.
  fatten : float, default=2
      A multiplicative factor used to increase the size of the
      middle bar across the box.
class_docstr_tok: ["Box","and","whiskers","plot","{","usage","}","Parameters","--","--","--","--","--","{","common_parameters","}","width",":","float",",","default=None","Box","width",".","If","`","None","`","{",".py","}",",","the","width","is","set","to","`","90","%","`","of","the","resolution","of","the","data",".","Note","that","if","the","stat","has","a","width","parameter",",","that","takes","precedence","over","this","one",".","outlier_alpha",":","float",",","default=1","Transparency","of","the","outlier","points",".","outlier_color",":","str","|","tuple",",","default=None","Color","of","the","outlier","points",".","outlier_shape",":","str",",","default=","''","o","''","Shape","of","the","outlier","points",".","An","empty","string","hides","the","outliers",".","outlier_size",":","float",",","default=1.5","Size","of","the","outlier","points",".","outlier_stroke",":","float",",","default=0.5","Stroke-size","of","the","outlier","points",".","notch",":","bool",",","default=False","Whether","the","boxes","should","have","a","notch",".","varwidth",":","bool",",","default=False","If","`","True","`","{",".py","}",",","boxes","are","drawn","with","widths","proportional","to","the","square-roots","of","the","number","of","observations","in","the","groups",".","notchwidth",":","float",",","default=0.5","Width","of","notch","relative","to","the","body","width",".","fatten",":","float",",","default=2","A","multiplicative","factor","used","to","increase","the","size","of","the","middle","bar","across","the","box","."]
code: def draw_group(
      data: pd.DataFrame,
      panel_params: panel_view,
      coord: Coord,
      ax: Axes,
      **params: Any,
  ):
      def flat(*args: pd.Series[Any]) -> npt.NDArray[Any]:
          """Flatten list-likes"""
          return np.hstack(args)
  
      common_columns = [
          "color",
          "size",
          "linetype",
          "fill",
          "group",
          "alpha",
          "shape",
      ]
      # whiskers
      whiskers = pd.DataFrame(
          {
              "x": flat(data["x"], data["x"]),
              "y": flat(data["upper"], data["lower"]),
              "yend": flat(data["ymax"], data["ymin"]),
              "alpha": 1,
          }
      )
      whiskers["xend"] = whiskers["x"]
      copy_missing_columns(whiskers, data[common_columns])
  
      # box
      box_columns = ["xmin", "xmax", "lower", "middle", "upper"]
      box = data[common_columns + box_columns].copy()
      box.rename(
          columns={"lower": "ymin", "middle": "y", "upper": "ymax"},
          inplace=True,
      )
  
      # notch
      if params["notch"]:
          box["ynotchlower"] = data["notchlower"]
          box["ynotchupper"] = data["notchupper"]
  
      # outliers
      num_outliers = len(data["outliers"].iloc[0])
      if num_outliers:
  
          def outlier_value(param: str) -> Any:
              oparam = f"outlier_{param}"
              if params[oparam] is not None:
                  return params[oparam]
              return data[param].iloc[0]
  
          outliers = pd.DataFrame(
              {
                  "y": data["outliers"].iloc[0],
                  "x": np.repeat(data["x"].iloc[0], num_outliers),
                  "fill": [None] * num_outliers,
              }
          )
          outliers["alpha"] = outlier_value("alpha")
          outliers["color"] = outlier_value("color")
          outliers["shape"] = outlier_value("shape")
          outliers["size"] = outlier_value("size")
          outliers["stroke"] = outlier_value("stroke")
          geom_point.draw_group(
              outliers, panel_params, coord, ax, **params
          )
  
      # plot
      geom_segment.draw_group(
          whiskers, panel_params, coord, ax, **params
      )
      geom_crossbar.draw_group(box, panel_params, coord, ax, **params)
  
file_path: plotnine/plotnine/geoms/geom_boxplot.py
imports: from __future__ import annotations
  import typing
  from warnings import warn
  import numpy
  import pandas
  from .._utils import SIZE_FACTOR, copy_missing_columns, resolution, to_rgba
  from ..doctools import document
  from ..exceptions import PlotnineWarning
  from ..positions import position_dodge2
  from ..positions.position import position
  from .geom import geom
  from .geom_crossbar import geom_crossbar
  from .geom_point import geom_point
  from .geom_segment import geom_segment
label_desc: Use image node_id 3 for calling the geom_boxplot obj's underlying member method code with example usage: obj.draw_group(data, panel_params, coord, ax) and returns: np, data, params