class_docstr: Displacement and narrowing of overlapping marks along orientation axis.
  
  Parameters
  ----------
  empty : {'keep', 'drop', 'fill'}
  gap : float
      Size of gap between dodged marks.
  by : list of variable names
      Variables to apply the movement to, otherwise use all.
  
  Examples
  --------
  .. include:: ../docstrings/objects.Dodge.rst
class_docstr_tok: ["Displacement","and","narrowing","of","overlapping","marks","along","orientation","axis",".","Parameters","--","--","--","--","--","empty",":","{","'keep","'",",","'drop","'",",","'fill","'","}","gap",":","float","Size","of","gap","between","dodged","marks",".","by",":","list","of","variable","names","Variables","to","apply","the","movement","to",",","otherwise","use","all",".","Examples","--","--","--","--","..","include",":",":","..","\/docstrings\/objects.Dodge.rst"]
code: def __call__(
      self,
      data: DataFrame,
      groupby: GroupBy,
      orient: str,
      scales: dict[str, Scale],
  ) -> DataFrame:
      grouping_vars = [v for v in groupby.order if v in data]
      groups = groupby.agg(data, {"width": "max"})
      if self.empty == "fill":
          groups = groups.dropna()
  
      def groupby_pos(s):
          grouper = [
              groups[v] for v in [orient, "col", "row"] if v in data
          ]
          return s.groupby(grouper, sort=False, observed=True)
  
      def scale_widths(w):
          # TODO what value to fill missing widths??? Hard problem...
          # TODO short circuit this if outer widths has no variance?
          empty = 0 if self.empty == "fill" else w.mean()
          filled = w.fillna(empty)
          scale = filled.max()
          norm = filled.sum()
          if self.empty == "keep":
              w = filled
          return w / norm * scale
  
      def widths_to_offsets(w):
          return w.shift(1).fillna(0).cumsum() + (w - w.sum()) / 2
  
      new_widths = groupby_pos(groups["width"]).transform(scale_widths)
      offsets = groupby_pos(new_widths).transform(widths_to_offsets)
  
      if self.gap:
          new_widths *= 1 - self.gap
  
      groups["_dodged"] = groups[orient] + offsets
      groups["width"] = new_widths
  
      out = (
          data.drop("width", axis=1)
          .merge(groups, on=grouping_vars, how="left")
          .drop(orient, axis=1)
          .rename(columns={"_dodged": orient})
      )
  
      return out
  
imports: from __future__ import annotations
  from dataclasses import dataclass
  from typing import ClassVar, Callable, Optional, Union, cast
  import numpy
  from pandas import DataFrame
  from seaborn._core.groupby import GroupBy
  from seaborn._core.scales import Scale
  from seaborn._core.typing import Default
label_desc: Use image node_id 1 for calling the Dodge obj's underlying member method code with example usage: obj.__call__(data, groupby, orient, scales) and returns: out, s, unknown, unknown