plotnine 0.15.0.dev3__py3-none-any.whl → 0.15.2__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (139) hide show
  1. plotnine/__init__.py +2 -0
  2. plotnine/_mpl/layout_manager/_engine.py +1 -1
  3. plotnine/_mpl/layout_manager/_layout_items.py +126 -41
  4. plotnine/_mpl/layout_manager/_layout_tree.py +712 -314
  5. plotnine/_mpl/layout_manager/_spaces.py +305 -101
  6. plotnine/_mpl/patches.py +70 -34
  7. plotnine/_mpl/text.py +144 -63
  8. plotnine/_mpl/utils.py +1 -1
  9. plotnine/_utils/__init__.py +50 -107
  10. plotnine/_utils/context.py +78 -2
  11. plotnine/_utils/ipython.py +35 -51
  12. plotnine/_utils/quarto.py +26 -0
  13. plotnine/_utils/yippie.py +115 -0
  14. plotnine/composition/__init__.py +11 -0
  15. plotnine/composition/_beside.py +55 -0
  16. plotnine/composition/_compose.py +471 -0
  17. plotnine/composition/_plot_spacer.py +60 -0
  18. plotnine/composition/_stack.py +55 -0
  19. plotnine/coords/coord.py +3 -3
  20. plotnine/data/__init__.py +31 -0
  21. plotnine/data/anscombe-quartet.csv +45 -0
  22. plotnine/doctools.py +4 -4
  23. plotnine/facets/facet.py +4 -4
  24. plotnine/facets/strips.py +17 -28
  25. plotnine/geoms/annotate.py +13 -13
  26. plotnine/geoms/annotation_logticks.py +7 -8
  27. plotnine/geoms/annotation_stripes.py +6 -6
  28. plotnine/geoms/geom.py +60 -27
  29. plotnine/geoms/geom_abline.py +3 -2
  30. plotnine/geoms/geom_area.py +2 -2
  31. plotnine/geoms/geom_bar.py +1 -0
  32. plotnine/geoms/geom_bin_2d.py +6 -2
  33. plotnine/geoms/geom_blank.py +0 -3
  34. plotnine/geoms/geom_boxplot.py +8 -4
  35. plotnine/geoms/geom_col.py +2 -2
  36. plotnine/geoms/geom_count.py +6 -2
  37. plotnine/geoms/geom_crossbar.py +3 -3
  38. plotnine/geoms/geom_density_2d.py +6 -2
  39. plotnine/geoms/geom_dotplot.py +2 -2
  40. plotnine/geoms/geom_errorbar.py +2 -2
  41. plotnine/geoms/geom_errorbarh.py +2 -2
  42. plotnine/geoms/geom_histogram.py +1 -1
  43. plotnine/geoms/geom_hline.py +3 -2
  44. plotnine/geoms/geom_linerange.py +2 -2
  45. plotnine/geoms/geom_map.py +5 -5
  46. plotnine/geoms/geom_path.py +11 -12
  47. plotnine/geoms/geom_point.py +4 -5
  48. plotnine/geoms/geom_pointdensity.py +4 -0
  49. plotnine/geoms/geom_pointrange.py +3 -5
  50. plotnine/geoms/geom_polygon.py +2 -3
  51. plotnine/geoms/geom_qq.py +4 -0
  52. plotnine/geoms/geom_qq_line.py +4 -0
  53. plotnine/geoms/geom_quantile.py +4 -0
  54. plotnine/geoms/geom_raster.py +4 -5
  55. plotnine/geoms/geom_rect.py +3 -4
  56. plotnine/geoms/geom_ribbon.py +7 -7
  57. plotnine/geoms/geom_rug.py +1 -1
  58. plotnine/geoms/geom_segment.py +2 -2
  59. plotnine/geoms/geom_sina.py +3 -3
  60. plotnine/geoms/geom_smooth.py +7 -3
  61. plotnine/geoms/geom_step.py +2 -2
  62. plotnine/geoms/geom_text.py +2 -3
  63. plotnine/geoms/geom_violin.py +8 -5
  64. plotnine/geoms/geom_vline.py +3 -2
  65. plotnine/ggplot.py +64 -85
  66. plotnine/guides/guide.py +7 -10
  67. plotnine/guides/guide_colorbar.py +3 -3
  68. plotnine/guides/guide_legend.py +3 -3
  69. plotnine/guides/guides.py +6 -6
  70. plotnine/helpers.py +49 -0
  71. plotnine/iapi.py +28 -5
  72. plotnine/labels.py +3 -3
  73. plotnine/layer.py +36 -19
  74. plotnine/mapping/_atomic.py +178 -0
  75. plotnine/mapping/_env.py +13 -2
  76. plotnine/mapping/_eval_environment.py +1 -1
  77. plotnine/mapping/aes.py +85 -49
  78. plotnine/scales/__init__.py +2 -0
  79. plotnine/scales/limits.py +7 -7
  80. plotnine/scales/scale.py +3 -3
  81. plotnine/scales/scale_color.py +82 -18
  82. plotnine/scales/scale_continuous.py +6 -4
  83. plotnine/scales/scale_datetime.py +28 -14
  84. plotnine/scales/scale_discrete.py +1 -1
  85. plotnine/scales/scale_identity.py +21 -2
  86. plotnine/scales/scale_manual.py +8 -2
  87. plotnine/scales/scale_xy.py +2 -2
  88. plotnine/stats/binning.py +4 -1
  89. plotnine/stats/smoothers.py +23 -36
  90. plotnine/stats/stat.py +20 -32
  91. plotnine/stats/stat_bin.py +6 -5
  92. plotnine/stats/stat_bin_2d.py +11 -9
  93. plotnine/stats/stat_bindot.py +13 -16
  94. plotnine/stats/stat_boxplot.py +6 -6
  95. plotnine/stats/stat_count.py +6 -9
  96. plotnine/stats/stat_density.py +7 -10
  97. plotnine/stats/stat_density_2d.py +12 -8
  98. plotnine/stats/stat_ecdf.py +7 -6
  99. plotnine/stats/stat_ellipse.py +9 -6
  100. plotnine/stats/stat_function.py +10 -8
  101. plotnine/stats/stat_hull.py +6 -3
  102. plotnine/stats/stat_identity.py +5 -2
  103. plotnine/stats/stat_pointdensity.py +5 -7
  104. plotnine/stats/stat_qq.py +46 -20
  105. plotnine/stats/stat_qq_line.py +16 -11
  106. plotnine/stats/stat_quantile.py +15 -9
  107. plotnine/stats/stat_sina.py +13 -15
  108. plotnine/stats/stat_smooth.py +8 -10
  109. plotnine/stats/stat_sum.py +5 -2
  110. plotnine/stats/stat_summary.py +7 -10
  111. plotnine/stats/stat_summary_bin.py +11 -14
  112. plotnine/stats/stat_unique.py +5 -2
  113. plotnine/stats/stat_ydensity.py +8 -11
  114. plotnine/themes/elements/__init__.py +2 -1
  115. plotnine/themes/elements/element_line.py +17 -9
  116. plotnine/themes/elements/margin.py +64 -1
  117. plotnine/themes/theme.py +9 -1
  118. plotnine/themes/theme_538.py +0 -1
  119. plotnine/themes/theme_bw.py +0 -1
  120. plotnine/themes/theme_dark.py +0 -1
  121. plotnine/themes/theme_gray.py +6 -5
  122. plotnine/themes/theme_light.py +1 -1
  123. plotnine/themes/theme_matplotlib.py +5 -5
  124. plotnine/themes/theme_seaborn.py +7 -4
  125. plotnine/themes/theme_void.py +9 -8
  126. plotnine/themes/theme_xkcd.py +0 -1
  127. plotnine/themes/themeable.py +109 -31
  128. plotnine/typing.py +17 -6
  129. plotnine/watermark.py +3 -3
  130. {plotnine-0.15.0.dev3.dist-info → plotnine-0.15.2.dist-info}/METADATA +13 -6
  131. plotnine-0.15.2.dist-info/RECORD +221 -0
  132. {plotnine-0.15.0.dev3.dist-info → plotnine-0.15.2.dist-info}/WHEEL +1 -1
  133. plotnine/plot_composition/__init__.py +0 -10
  134. plotnine/plot_composition/_compose.py +0 -436
  135. plotnine/plot_composition/_spacer.py +0 -32
  136. plotnine-0.15.0.dev3.dist-info/RECORD +0 -215
  137. /plotnine/{plot_composition → composition}/_plotspec.py +0 -0
  138. {plotnine-0.15.0.dev3.dist-info → plotnine-0.15.2.dist-info}/licenses/LICENSE +0 -0
  139. {plotnine-0.15.0.dev3.dist-info → plotnine-0.15.2.dist-info}/top_level.txt +0 -0
plotnine/doctools.py CHANGED
@@ -71,7 +71,7 @@ STAT_SIGNATURE_TPL = """
71
71
 
72
72
  common_params_doc = {
73
73
  "mapping": """\
74
- Aesthetic mappings created with [aes](:class:`plotnine.mapping.aes`). If \
74
+ Aesthetic mappings created with [aes](:class:`plotnine.mapping.aes.aes`). If \
75
75
  specified and `inherit_aes=True`{.py}, it is combined with the default \
76
76
  mapping for the plot. You must supply mapping if there is no plot mapping.""",
77
77
  "data": """\
@@ -103,7 +103,7 @@ the final image is in vector format.""",
103
103
 
104
104
 
105
105
  GEOM_PARAMS_TPL = """
106
- mapping : ~plotnine.mapping.aes, default=None
106
+ mapping : ~plotnine.mapping.aes.aes, default=None
107
107
  {mapping}
108
108
  {_aesthetics_doc}
109
109
  data : ~pandas.DataFrame, default=None
@@ -124,7 +124,7 @@ raster : bool, default={default_raster}
124
124
  """
125
125
 
126
126
  STAT_PARAMS_TPL = """
127
- mapping : ~plotnine.mapping.aes, default=None
127
+ mapping : ~plotnine.mapping.aes.aes, default=None
128
128
  {mapping}
129
129
  {_aesthetics_doc}
130
130
  data : ~pandas.DataFrame, default=None
@@ -451,7 +451,7 @@ def document_geom(geom: type[geom]) -> type[geom]:
451
451
  table = dict_to_table(("Aesthetic", "Default value"), contents)
452
452
  aesthetics_table = AESTHETICS_TABLE_TPL.format(table=table)
453
453
  tpl = dedent(geom._aesthetics_doc).strip()
454
- aesthetics_doc = tpl.format(aesthetics_table=aesthetics_table)
454
+ aesthetics_doc = tpl.replace("{aesthetics_table}", aesthetics_table)
455
455
  aesthetics_doc = indent(aesthetics_doc, " " * 4)
456
456
 
457
457
  # common_parameters
plotnine/facets/facet.py CHANGED
@@ -130,13 +130,13 @@ class facet:
130
130
  "y": scales in ("free_y", "free"),
131
131
  }
132
132
 
133
- def __radd__(self, plot: ggplot) -> ggplot:
133
+ def __radd__(self, other: ggplot) -> ggplot:
134
134
  """
135
135
  Add facet to ggplot object
136
136
  """
137
- plot.facet = copy(self)
138
- plot.facet.environment = plot.environment
139
- return plot
137
+ other.facet = copy(self)
138
+ other.facet.environment = other.environment
139
+ return other
140
140
 
141
141
  def setup(self, plot: ggplot):
142
142
  self.plot = plot
plotnine/facets/strips.py CHANGED
@@ -67,56 +67,45 @@ class strip:
67
67
  if position == "top":
68
68
  # The x & y values are just starting locations
69
69
  # The final location is determined by the layout manager.
70
- y = 1
70
+ bg_y = 1
71
71
  ha = theme.getp(("strip_text_x", "ha"), "center")
72
- va = theme.getp(("strip_text_x", "va"), "bottom")
72
+ va = theme.getp(("strip_text_x", "va"), "center")
73
73
  rotation = theme.getp(("strip_text_x", "rotation"))
74
- box_width = 1
75
- box_height = 0 # Determined by the text size
76
- # TODO: Allow two unique paddings for either side.
77
- # Requires implementing an mpl.patches.boxstyle that recognises
78
- # two padding values.
79
- strip_text_margin = (
80
- theme.getp(("strip_text_x", "margin")).to("lines").b
81
- )
74
+ bg_height = 0 # Determined by the text size
75
+ margin = theme.getp(("strip_text_x", "margin")).to("lines")
82
76
  strip_align = theme.getp("strip_align_x")
83
77
 
84
78
  # x & width properties of the background slide and
85
79
  # shrink the strip horizontally.
86
- x = theme.getp(("strip_text_x", "x"), 0)
87
- box_width = theme.getp(("strip_background_x", "width"), 1)
80
+ bg_x = theme.getp(("strip_text_x", "x"), 0)
81
+ bg_width = theme.getp(("strip_background_x", "width"), 1)
88
82
 
89
83
  elif position == "right":
90
84
  # The x & y values are just starting locations
91
85
  # The final location is determined by the layout manager.
92
- x = 1
93
- ha = theme.getp(("strip_text_y", "ha"), "left")
86
+ bg_x = 1
87
+ ha = theme.getp(("strip_text_y", "ha"), "center")
94
88
  va = theme.getp(("strip_text_y", "va"), "center")
95
89
  rotation = theme.getp(("strip_text_y", "rotation"))
96
- box_width = 0 # Determine by the text height
97
- # TODO: Allow two unique paddings for either side.
98
- # Requires implementing an mpl.patches.boxstyle that recognises
99
- # two padding values.
100
- strip_text_margin = (
101
- theme.getp(("strip_text_y", "margin")).to("lines").r
102
- )
90
+ bg_width = 0 # Determine by the text height
91
+ margin = theme.getp(("strip_text_y", "margin")).to("lines")
103
92
  strip_align = theme.getp("strip_align_y")
104
93
 
105
94
  # y & height properties of the background slide and
106
95
  # shrink the strip vertically.
107
- y = theme.getp(("strip_text_y", "y"), 0)
108
- box_height = theme.getp(("strip_background_y", "height"), 1)
96
+ bg_y = theme.getp(("strip_text_y", "y"), 0)
97
+ bg_height = theme.getp(("strip_background_y", "height"), 1)
109
98
  else:
110
99
  raise ValueError(f"Unknown position for strip text: {position!r}")
111
100
 
112
101
  return strip_draw_info(
113
- x=x,
114
- y=y,
102
+ bg_x=bg_x,
103
+ bg_y=bg_y,
115
104
  ha=ha,
116
105
  va=va,
117
- box_width=box_width,
118
- box_height=box_height,
119
- strip_text_margin=strip_text_margin,
106
+ bg_width=bg_width,
107
+ bg_height=bg_height,
108
+ margin=margin,
120
109
  strip_align=strip_align,
121
110
  position=position,
122
111
  label=self.label_info.text(),
@@ -64,16 +64,16 @@ class annotate:
64
64
  def __init__(
65
65
  self,
66
66
  geom: str | type[geom_base_class],
67
- x: float | None = None,
68
- y: float | None = None,
69
- xmin: float | None = None,
70
- xmax: float | None = None,
71
- xend: float | None = None,
72
- xintercept: float | None = None,
73
- ymin: float | None = None,
74
- ymax: float | None = None,
75
- yend: float | None = None,
76
- yintercept: float | None = None,
67
+ x: float | list[float] | None = None,
68
+ y: float | list[float] | None = None,
69
+ xmin: float | list[float] | None = None,
70
+ xmax: float | list[float] | None = None,
71
+ xend: float | list[float] | None = None,
72
+ xintercept: float | list[float] | None = None,
73
+ ymin: float | list[float] | None = None,
74
+ ymax: float | list[float] | None = None,
75
+ yend: float | list[float] | None = None,
76
+ yintercept: float | list[float] | None = None,
77
77
  **kwargs: Any,
78
78
  ):
79
79
  variables = locals()
@@ -131,12 +131,12 @@ class annotate:
131
131
  **kwargs,
132
132
  )
133
133
 
134
- def __radd__(self, plot: ggplot) -> ggplot:
134
+ def __radd__(self, other: ggplot) -> ggplot:
135
135
  """
136
136
  Add to ggplot
137
137
  """
138
- plot += self.to_layer() # Add layer
139
- return plot
138
+ other += self.to_layer() # Add layer
139
+ return other
140
140
 
141
141
  def to_layer(self) -> layer:
142
142
  """
@@ -46,9 +46,7 @@ class _geom_logticks(geom_rug):
46
46
  }
47
47
  draw_legend = staticmethod(geom_path.draw_legend)
48
48
 
49
- def draw_layer(
50
- self, data: pd.DataFrame, layout: Layout, coord: coord, **params: Any
51
- ):
49
+ def draw_layer(self, data: pd.DataFrame, layout: Layout, coord: coord):
52
50
  """
53
51
  Draw ticks on every panel
54
52
  """
@@ -56,7 +54,7 @@ class _geom_logticks(geom_rug):
56
54
  ploc = pid - 1
57
55
  panel_params = layout.panel_params[ploc]
58
56
  ax = layout.axs[ploc]
59
- self.draw_panel(data, panel_params, coord, ax, **params)
57
+ self.draw_panel(data, panel_params, coord, ax)
60
58
 
61
59
  @staticmethod
62
60
  def _check_log_scale(
@@ -184,8 +182,8 @@ class _geom_logticks(geom_rug):
184
182
  panel_params: panel_view,
185
183
  coord: coord,
186
184
  ax: Axes,
187
- **params: Any,
188
185
  ):
186
+ params = self.params
189
187
  # Any passed data is ignored, the relevant data is created
190
188
  sides = params["sides"]
191
189
  lengths = params["lengths"]
@@ -203,9 +201,8 @@ class _geom_logticks(geom_rug):
203
201
  ):
204
202
  for position, length in zip(tick_positions, lengths):
205
203
  data = pd.DataFrame({axis: position, **_aesthetics})
206
- geom.draw_group(
207
- data, panel_params, coord, ax, length=length, **params
208
- )
204
+ params["length"] = length
205
+ geom.draw_group(data, panel_params, coord, ax, params)
209
206
 
210
207
  if isinstance(coord, coord_flip):
211
208
  tick_range_x = panel_params.y.range
@@ -285,4 +282,6 @@ class annotation_logticks(annotate):
285
282
  linetype=linetype,
286
283
  lengths=lengths,
287
284
  base=base,
285
+ inherit_aes=False,
286
+ show_legend=False,
288
287
  )
@@ -72,6 +72,8 @@ class annotation_stripes(annotate):
72
72
  fill_range=fill_range,
73
73
  extend=extend,
74
74
  direction=direction,
75
+ inherit_aes=False,
76
+ show_legend=False,
75
77
  **kwargs,
76
78
  )
77
79
 
@@ -94,9 +96,7 @@ class _geom_stripes(geom):
94
96
  }
95
97
  draw_legend = staticmethod(geom_polygon.draw_legend)
96
98
 
97
- def draw_layer(
98
- self, data: pd.DataFrame, layout: Layout, coord: coord, **params: Any
99
- ):
99
+ def draw_layer(self, data: pd.DataFrame, layout: Layout, coord: coord):
100
100
  """
101
101
  Draw stripes on every panel
102
102
  """
@@ -104,7 +104,7 @@ class _geom_stripes(geom):
104
104
  ploc = pid - 1
105
105
  panel_params = layout.panel_params[ploc]
106
106
  ax = layout.axs[ploc]
107
- self.draw_group(data, panel_params, coord, ax, **params)
107
+ self.draw_group(data, panel_params, coord, ax, self.params)
108
108
 
109
109
  @staticmethod
110
110
  def draw_group(
@@ -112,7 +112,7 @@ class _geom_stripes(geom):
112
112
  panel_params: panel_view,
113
113
  coord: coord,
114
114
  ax: Axes,
115
- **params: Any,
115
+ params: dict[str, Any],
116
116
  ):
117
117
  extend = params["extend"]
118
118
  fill_range = params["fill_range"]
@@ -193,4 +193,4 @@ class _geom_stripes(geom):
193
193
  }
194
194
  )
195
195
 
196
- return geom_rect.draw_group(data, panel_params, coord, ax, **params)
196
+ return geom_rect.draw_group(data, panel_params, coord, ax, params)
plotnine/geoms/geom.py CHANGED
@@ -2,18 +2,20 @@ from __future__ import annotations
2
2
 
3
3
  import typing
4
4
  from abc import ABC
5
+ from contextlib import suppress
5
6
  from copy import deepcopy
6
7
  from itertools import chain, repeat
7
8
 
9
+ import numpy as np
10
+
8
11
  from .._utils import (
9
12
  data_mapping_as_kwargs,
10
- is_list_like,
11
13
  remove_missing,
12
14
  )
13
15
  from .._utils.registry import Register, Registry
14
16
  from ..exceptions import PlotnineError
15
17
  from ..layer import layer
16
- from ..mapping.aes import is_valid_aesthetic, rename_aesthetics
18
+ from ..mapping.aes import rename_aesthetics
17
19
  from ..mapping.evaluation import evaluate
18
20
  from ..positions.position import position
19
21
  from ..stats.stat import stat
@@ -171,6 +173,26 @@ class geom(ABC, metaclass=Register):
171
173
 
172
174
  return result
173
175
 
176
+ def setup_params(self, data: pd.DataFrame):
177
+ """
178
+ Override this method to verify and/or adjust parameters
179
+
180
+ Parameters
181
+ ----------
182
+ data :
183
+ Data
184
+ """
185
+
186
+ def setup_aes_params(self, data: pd.DataFrame):
187
+ """
188
+ Override this method to verify and/or adjust aesthetic parameters
189
+
190
+ Parameters
191
+ ----------
192
+ data :
193
+ Data
194
+ """
195
+
174
196
  def setup_data(self, data: pd.DataFrame) -> pd.DataFrame:
175
197
  """
176
198
  Modify the data before drawing takes place
@@ -224,6 +246,9 @@ class geom(ABC, metaclass=Register):
224
246
  :
225
247
  Data used for drawing the geom.
226
248
  """
249
+ from plotnine.mapping import _atomic as atomic
250
+ from plotnine.mapping._atomic import ae_value
251
+
227
252
  missing_aes = (
228
253
  self.DEFAULT_AES.keys()
229
254
  - self.aes_params.keys()
@@ -240,30 +265,39 @@ class geom(ABC, metaclass=Register):
240
265
  data[ae] = evaled[ae]
241
266
 
242
267
  num_panels = len(data["PANEL"].unique()) if "PANEL" in data else 1
268
+ across_panels = num_panels > 1 and not self.params["inherit_aes"]
243
269
 
244
- # Aesthetics set as parameters to the geom/stat
270
+ # Aesthetics set as parameters in the geom/stat
245
271
  for ae, value in self.aes_params.items():
246
- try:
272
+ if isinstance(value, (str, int, float, np.integer, np.floating)):
273
+ data[ae] = value
274
+ elif isinstance(value, ae_value):
275
+ data[ae] = value * len(data)
276
+ elif across_panels:
277
+ value = list(chain(*repeat(value, num_panels)))
247
278
  data[ae] = value
248
- except ValueError as e:
249
- # sniff out the special cases, like custom
250
- # tupled linetypes, shapes and colors
251
- if is_valid_aesthetic(value, ae):
252
- data[ae] = [value] * len(data)
253
- elif num_panels > 1 and is_list_like(value):
254
- data[ae] = list(chain(*repeat(value, num_panels)))
255
- else:
256
- msg = (
257
- f"'{value}' does not look like a "
258
- f"valid value for `{ae}`"
259
- )
279
+ else:
280
+ # Try to make sense of aesthetics whose values can be tuples
281
+ # or sequences of sorts.
282
+ ae_value_cls: type[ae_value] | None = getattr(atomic, ae, None)
283
+ if ae_value_cls:
284
+ with suppress(ValueError):
285
+ data[ae] = ae_value_cls(value) * len(data)
286
+ continue
287
+
288
+ # This should catch the aesthetic assignments to
289
+ # non-numeric or non-string values or sequence of values.
290
+ # e.g. x=datetime, x=Sequence[datetime],
291
+ # x=Sequence[float], shape=Sequence[str]
292
+ try:
293
+ data[ae] = value
294
+ except ValueError as e:
295
+ msg = f"'{ae}={value}' does not look like a valid value"
260
296
  raise PlotnineError(msg) from e
261
297
 
262
298
  return data
263
299
 
264
- def draw_layer(
265
- self, data: pd.DataFrame, layout: Layout, coord: coord, **params: Any
266
- ):
300
+ def draw_layer(self, data: pd.DataFrame, layout: Layout, coord: coord):
267
301
  """
268
302
  Draw layer across all panels
269
303
 
@@ -289,7 +323,7 @@ class geom(ABC, metaclass=Register):
289
323
  ploc = pdata["PANEL"].iloc[0] - 1
290
324
  panel_params = layout.panel_params[ploc]
291
325
  ax = layout.axs[ploc]
292
- self.draw_panel(pdata, panel_params, coord, ax, **params)
326
+ self.draw_panel(pdata, panel_params, coord, ax)
293
327
 
294
328
  def draw_panel(
295
329
  self,
@@ -297,7 +331,6 @@ class geom(ABC, metaclass=Register):
297
331
  panel_params: panel_view,
298
332
  coord: coord,
299
333
  ax: Axes,
300
- **params: Any,
301
334
  ):
302
335
  """
303
336
  Plot all groups
@@ -331,7 +364,7 @@ class geom(ABC, metaclass=Register):
331
364
  """
332
365
  for _, gdata in data.groupby("group"):
333
366
  gdata.reset_index(inplace=True, drop=True)
334
- self.draw_group(gdata, panel_params, coord, ax, **params)
367
+ self.draw_group(gdata, panel_params, coord, ax, self.params)
335
368
 
336
369
  @staticmethod
337
370
  def draw_group(
@@ -339,7 +372,7 @@ class geom(ABC, metaclass=Register):
339
372
  panel_params: panel_view,
340
373
  coord: coord,
341
374
  ax: Axes,
342
- **params: Any,
375
+ params: dict[str, Any],
343
376
  ):
344
377
  """
345
378
  Plot data belonging to a group.
@@ -376,7 +409,7 @@ class geom(ABC, metaclass=Register):
376
409
  panel_params: panel_view,
377
410
  coord: coord,
378
411
  ax: Axes,
379
- **params: Any,
412
+ params: dict[str, Any],
380
413
  ):
381
414
  """
382
415
  Plot data belonging to a unit.
@@ -426,7 +459,7 @@ class geom(ABC, metaclass=Register):
426
459
  msg = "The geom should implement this method."
427
460
  raise NotImplementedError(msg)
428
461
 
429
- def __radd__(self, plot: ggplot) -> ggplot:
462
+ def __radd__(self, other: ggplot) -> ggplot:
430
463
  """
431
464
  Add layer representing geom object on the right
432
465
 
@@ -440,8 +473,8 @@ class geom(ABC, metaclass=Register):
440
473
  :
441
474
  ggplot object with added layer.
442
475
  """
443
- plot += self.to_layer() # Add layer
444
- return plot
476
+ other += self.to_layer() # Add layer
477
+ return other
445
478
 
446
479
  def to_layer(self) -> layer:
447
480
  """
@@ -102,7 +102,6 @@ class geom_abline(geom):
102
102
  panel_params: panel_view,
103
103
  coord: coord,
104
104
  ax: Axes,
105
- **params: Any,
106
105
  ):
107
106
  """
108
107
  Plot all groups
@@ -116,4 +115,6 @@ class geom_abline(geom):
116
115
 
117
116
  for _, gdata in data.groupby("group"):
118
117
  gdata.reset_index(inplace=True)
119
- geom_segment.draw_group(gdata, panel_params, coord, ax, **params)
118
+ geom_segment.draw_group(
119
+ gdata, panel_params, coord, ax, self.params
120
+ )
@@ -14,12 +14,12 @@ class geom_area(geom_ribbon):
14
14
  """
15
15
  Area plot
16
16
 
17
+ {usage}
18
+
17
19
  An area plot is a special case of geom_ribbon,
18
20
  where the minimum of the range is fixed to 0,
19
21
  and the position adjustment defaults to 'stack'.
20
22
 
21
- {usage}
22
-
23
23
  Parameters
24
24
  ----------
25
25
  {common_parameters}
@@ -32,6 +32,7 @@ class geom_bar(geom_rect):
32
32
  See Also
33
33
  --------
34
34
  plotnine.geom_histogram
35
+ plotnine.stat_count : The default `stat` for this `geom`.
35
36
  """
36
37
 
37
38
  REQUIRED_AES = {"x", "y"}
@@ -7,16 +7,20 @@ class geom_bin_2d(geom_rect):
7
7
  """
8
8
  Heatmap of 2d bin counts
9
9
 
10
+ {usage}
11
+
10
12
  Divides the plane into rectangles, counts the number of
11
13
  cases in each rectangle, and then (by default) maps the number
12
14
  of cases to the rectangle's fill. This is a useful alternative
13
15
  to geom_point in the presence of overplotting.
14
16
 
15
- {usage}
16
-
17
17
  Parameters
18
18
  ----------
19
19
  {common_parameters}
20
+
21
+ See Also
22
+ --------
23
+ plotnine.stat_bin_2d : The default stat for this `geom`.
20
24
  """
21
25
 
22
26
  DEFAULT_PARAMS = {"stat": "bin_2d", "position": "identity", "na_rm": False}
@@ -6,8 +6,6 @@ from ..doctools import document
6
6
  from .geom import geom
7
7
 
8
8
  if typing.TYPE_CHECKING:
9
- from typing import Any
10
-
11
9
  import pandas as pd
12
10
  from matplotlib.axes import Axes
13
11
 
@@ -39,7 +37,6 @@ class geom_blank(geom):
39
37
  panel_params: panel_view,
40
38
  coord: coord,
41
39
  ax: Axes,
42
- **params: Any,
43
40
  ):
44
41
  pass
45
42
 
@@ -70,6 +70,10 @@ class geom_boxplot(geom):
70
70
  fatten : float, default=2
71
71
  A multiplicative factor used to increase the size of the
72
72
  middle bar across the box.
73
+
74
+ See Also
75
+ --------
76
+ plotnine.stat_boxplot : The default `stat` for this `geom`.
73
77
  """
74
78
 
75
79
  DEFAULT_AES = {
@@ -183,7 +187,7 @@ class geom_boxplot(geom):
183
187
  panel_params: panel_view,
184
188
  coord: coord,
185
189
  ax: Axes,
186
- **params: Any,
190
+ params: dict[str, Any],
187
191
  ):
188
192
  def flat(*args: pd.Series[Any]) -> npt.NDArray[Any]:
189
193
  """Flatten list-likes"""
@@ -245,11 +249,11 @@ class geom_boxplot(geom):
245
249
  outliers["shape"] = outlier_value("shape")
246
250
  outliers["size"] = outlier_value("size")
247
251
  outliers["stroke"] = outlier_value("stroke")
248
- geom_point.draw_group(outliers, panel_params, coord, ax, **params)
252
+ geom_point.draw_group(outliers, panel_params, coord, ax, params)
249
253
 
250
254
  # plot
251
- geom_segment.draw_group(whiskers, panel_params, coord, ax, **params)
252
- geom_crossbar.draw_group(box, panel_params, coord, ax, **params)
255
+ geom_segment.draw_group(whiskers, panel_params, coord, ax, params)
256
+ geom_crossbar.draw_group(box, panel_params, coord, ax, params)
253
257
 
254
258
  @staticmethod
255
259
  def draw_legend(
@@ -7,13 +7,13 @@ class geom_col(geom_bar):
7
7
  """
8
8
  Bar plot with base on the x-axis
9
9
 
10
+ {usage}
11
+
10
12
  This is an alternate version of [](`~plotnine.geoms.geom_bar`) that maps
11
13
  the height of bars to an existing variable in your data. If
12
14
  you want the height of the bar to represent a count of cases,
13
15
  use [](`~plotnine.geoms.geom_bar`).
14
16
 
15
- {usage}
16
-
17
17
  Parameters
18
18
  ----------
19
19
  {common_parameters}
@@ -7,15 +7,19 @@ class geom_count(geom_point):
7
7
  """
8
8
  Plot overlapping points
9
9
 
10
+ {usage}
11
+
10
12
  This is a variant [](`~plotnine.geoms.geom_point`) that counts the number
11
13
  of observations at each location, then maps the count to point
12
14
  area. It useful when you have discrete data and overplotting.
13
15
 
14
- {usage}
15
-
16
16
  Parameters
17
17
  ----------
18
18
  {common_parameters}
19
+
20
+ See Also
21
+ --------
22
+ plotnine.stat_sum : The default `stat` for this `geom`.
19
23
  """
20
24
 
21
25
  DEFAULT_PARAMS = {"stat": "sum", "position": "identity", "na_rm": False}
@@ -78,7 +78,7 @@ class geom_crossbar(geom):
78
78
  panel_params: panel_view,
79
79
  coord: coord,
80
80
  ax: Axes,
81
- **params: Any,
81
+ params: dict[str, Any],
82
82
  ):
83
83
  y = data["y"]
84
84
  xmin = data["xmin"]
@@ -160,8 +160,8 @@ class geom_crossbar(geom):
160
160
  )
161
161
 
162
162
  copy_missing_columns(box, data)
163
- geom_polygon.draw_group(box, panel_params, coord, ax, **params)
164
- geom_segment.draw_group(middle, panel_params, coord, ax, **params)
163
+ geom_polygon.draw_group(box, panel_params, coord, ax, params)
164
+ geom_segment.draw_group(middle, panel_params, coord, ax, params)
165
165
 
166
166
  @staticmethod
167
167
  def draw_legend(
@@ -7,13 +7,17 @@ class geom_density_2d(geom_path):
7
7
  """
8
8
  2D density estimate
9
9
 
10
- This is a 2d version of [](`~plotnine.geoms.geom_density`).
11
-
12
10
  {usage}
13
11
 
12
+ This is a 2d version of [](`~plotnine.geoms.geom_density`).
13
+
14
14
  Parameters
15
15
  ----------
16
16
  {common_parameters}
17
+
18
+ See Also
19
+ --------
20
+ plotnine.stat_density_2d : The default `stat` for this `geom`.
17
21
  """
18
22
 
19
23
  DEFAULT_PARAMS = {
@@ -46,7 +46,7 @@ class geom_dotplot(geom):
46
46
 
47
47
  See Also
48
48
  --------
49
- plotnine.stat_bindot
49
+ plotnine.stat_bindot : The default `stat` for this `geom`.
50
50
  """
51
51
 
52
52
  DEFAULT_AES = {"alpha": 1, "color": "black", "fill": "black"}
@@ -186,7 +186,7 @@ class geom_dotplot(geom):
186
186
  panel_params: panel_view,
187
187
  coord: coord,
188
188
  ax: Axes,
189
- **params: Any,
189
+ params: dict[str, Any],
190
190
  ):
191
191
  from matplotlib.collections import PatchCollection
192
192
  from matplotlib.patches import Ellipse