ggh4x-python 0.3.1.9000__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.
- ggh4x/__init__.py +140 -0
- ggh4x/_aimed_text_grob.py +432 -0
- ggh4x/_borrowed_ggplot2.py +273 -0
- ggh4x/_cli.py +84 -0
- ggh4x/_datasets.py +106 -0
- ggh4x/_download.py +111 -0
- ggh4x/_facet_helpers.py +313 -0
- ggh4x/_facet_utils.py +649 -0
- ggh4x/_gap_grobs.py +606 -0
- ggh4x/_registry.py +10 -0
- ggh4x/_rlang.py +93 -0
- ggh4x/_utils.py +150 -0
- ggh4x/_vctrs.py +233 -0
- ggh4x/conveniences.py +601 -0
- ggh4x/coord_axes_inside.py +380 -0
- ggh4x/element_part_rect.py +545 -0
- ggh4x/facet_grid2.py +1018 -0
- ggh4x/facet_manual.py +901 -0
- ggh4x/facet_nested.py +776 -0
- ggh4x/facet_nested_wrap.py +193 -0
- ggh4x/facet_wrap2.py +896 -0
- ggh4x/geom_box.py +536 -0
- ggh4x/geom_outline_point.py +444 -0
- ggh4x/geom_pointpath.py +259 -0
- ggh4x/geom_polygonraster.py +252 -0
- ggh4x/geom_rectrug.py +489 -0
- ggh4x/geom_text_aimed.py +279 -0
- ggh4x/guide_stringlegend.py +354 -0
- ggh4x/help_secondary.py +549 -0
- ggh4x/multiscale/__init__.py +51 -0
- ggh4x/multiscale/_multiscale_add.py +207 -0
- ggh4x/multiscale/scale_listed.py +167 -0
- ggh4x/multiscale/scale_manual.py +478 -0
- ggh4x/multiscale/scale_multi.py +393 -0
- ggh4x/panel_scales/__init__.py +58 -0
- ggh4x/panel_scales/at_panel.py +115 -0
- ggh4x/panel_scales/facetted_pos_scales.py +647 -0
- ggh4x/panel_scales/force_panelsize.py +411 -0
- ggh4x/panel_scales/scale_facet.py +222 -0
- ggh4x/position_disjoint_ranges.py +229 -0
- ggh4x/position_lineartrans.py +242 -0
- ggh4x/py.typed +0 -0
- ggh4x/resources/faithful.csv +273 -0
- ggh4x/resources/iris.csv +151 -0
- ggh4x/resources/mtcars.csv +33 -0
- ggh4x/resources/pressure.csv +20 -0
- ggh4x/resources/volcano.csv +87 -0
- ggh4x/save.py +255 -0
- ggh4x/stat_difference.py +388 -0
- ggh4x/stat_funxy.py +436 -0
- ggh4x/stat_rle.py +290 -0
- ggh4x/stat_rollingkernel.py +369 -0
- ggh4x/stat_theodensity.py +681 -0
- ggh4x/strip_nested.py +448 -0
- ggh4x/strip_split.py +687 -0
- ggh4x/strip_tag.py +636 -0
- ggh4x/strip_themed.py +232 -0
- ggh4x/strip_vanilla.py +1464 -0
- ggh4x/themes.py +31 -0
- ggh4x/themes_ggh4x.py +67 -0
- ggh4x_python-0.3.1.9000.dist-info/METADATA +40 -0
- ggh4x_python-0.3.1.9000.dist-info/RECORD +64 -0
- ggh4x_python-0.3.1.9000.dist-info/WHEEL +4 -0
- ggh4x_python-0.3.1.9000.dist-info/licenses/LICENSE +3 -0
ggh4x/stat_funxy.py
ADDED
|
@@ -0,0 +1,436 @@
|
|
|
1
|
+
"""Apply a function to position coordinates per group.
|
|
2
|
+
|
|
3
|
+
Python port of ``stat_funxy.R`` from the R package **ggh4x**.
|
|
4
|
+
|
|
5
|
+
The "function xy" stat applies a user-supplied function to the ``x`` and
|
|
6
|
+
``y`` aesthetics of a layer's positions, computed separately per group.
|
|
7
|
+
:func:`stat_centroid` and :func:`stat_midpoint` are convenience wrappers
|
|
8
|
+
that compute group centroids (means) and midpoints (``(min + max) / 2``)
|
|
9
|
+
respectively. :func:`stat_funxy` leaves the data unchanged by default but
|
|
10
|
+
can be supplied arbitrary functions and arguments.
|
|
11
|
+
|
|
12
|
+
R source
|
|
13
|
+
--------
|
|
14
|
+
``ggh4x/R/stat_funxy.R`` -- :class:`StatFunxy`, :func:`stat_funxy`,
|
|
15
|
+
:func:`stat_centroid`, :func:`stat_midpoint`.
|
|
16
|
+
|
|
17
|
+
Notes
|
|
18
|
+
-----
|
|
19
|
+
This statistic makes only a minimal attempt at ensuring that the results
|
|
20
|
+
of calling both functions are of equal length. Results of length one are
|
|
21
|
+
recycled to match the longest result (mirroring
|
|
22
|
+
``vctrs::vec_recycle_common``).
|
|
23
|
+
"""
|
|
24
|
+
|
|
25
|
+
from __future__ import annotations
|
|
26
|
+
|
|
27
|
+
from typing import Any, Callable, Dict, Mapping, Optional, Sequence
|
|
28
|
+
|
|
29
|
+
import numpy as np
|
|
30
|
+
import pandas as pd
|
|
31
|
+
|
|
32
|
+
from ggplot2_py import Stat
|
|
33
|
+
|
|
34
|
+
from ._cli import cli_abort
|
|
35
|
+
from ._vctrs import data_frame0, vec_recycle_common
|
|
36
|
+
|
|
37
|
+
__all__ = [
|
|
38
|
+
"StatFunxy",
|
|
39
|
+
"stat_funxy",
|
|
40
|
+
"stat_centroid",
|
|
41
|
+
"stat_midpoint",
|
|
42
|
+
]
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
# ---------------------------------------------------------------------------
|
|
46
|
+
# Lazy ``layer`` import (mirrors ggplot2_py.stat._layer; avoids importing the
|
|
47
|
+
# heavy layer machinery -- and any circular dependency -- at module import).
|
|
48
|
+
# ---------------------------------------------------------------------------
|
|
49
|
+
def _layer(**kwargs: Any) -> Any:
|
|
50
|
+
"""Construct a :class:`ggplot2_py.Layer`, importing ``layer`` lazily.
|
|
51
|
+
|
|
52
|
+
Parameters
|
|
53
|
+
----------
|
|
54
|
+
**kwargs : Any
|
|
55
|
+
Forwarded verbatim to :func:`ggplot2_py.layer.layer`.
|
|
56
|
+
|
|
57
|
+
Returns
|
|
58
|
+
-------
|
|
59
|
+
ggplot2_py.Layer
|
|
60
|
+
"""
|
|
61
|
+
from ggplot2_py.layer import layer
|
|
62
|
+
|
|
63
|
+
return layer(**kwargs)
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
# ---------------------------------------------------------------------------
|
|
67
|
+
# Helper reductions used by the wrapper constructors.
|
|
68
|
+
#
|
|
69
|
+
# R forwards ``na.rm = TRUE`` to ``mean``/``range``. NumPy's ``mean``/``min``/
|
|
70
|
+
# ``max`` have no ``na_rm`` keyword, so the wrappers translate to the
|
|
71
|
+
# NaN-aware reductions and accept (and honour) an ``na_rm`` keyword so the
|
|
72
|
+
# translated ``argx``/``argy`` dicts forward cleanly.
|
|
73
|
+
# ---------------------------------------------------------------------------
|
|
74
|
+
def _mean(x: Sequence[float], na_rm: bool = False) -> np.floating:
|
|
75
|
+
"""Arithmetic mean with optional NA removal (port of R ``mean``).
|
|
76
|
+
|
|
77
|
+
Parameters
|
|
78
|
+
----------
|
|
79
|
+
x : sequence of float
|
|
80
|
+
Values to average.
|
|
81
|
+
na_rm : bool, default False
|
|
82
|
+
Whether to ignore ``NaN`` values (R's ``na.rm``).
|
|
83
|
+
|
|
84
|
+
Returns
|
|
85
|
+
-------
|
|
86
|
+
numpy.floating
|
|
87
|
+
The (NaN-aware) mean of *x*.
|
|
88
|
+
"""
|
|
89
|
+
arr = np.asarray(x, dtype=float)
|
|
90
|
+
return np.nanmean(arr) if na_rm else np.mean(arr)
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
def _midpoint(x: Sequence[float], na_rm: bool = True) -> np.floating:
|
|
94
|
+
"""Midpoint of the data range: ``(min + max) / 2``.
|
|
95
|
+
|
|
96
|
+
Port of the closure defined inside R ``stat_midpoint`` --
|
|
97
|
+
``sum(range(x, na.rm = na.rm), na.rm = na.rm) / 2``.
|
|
98
|
+
|
|
99
|
+
Parameters
|
|
100
|
+
----------
|
|
101
|
+
x : sequence of float
|
|
102
|
+
Values to summarise.
|
|
103
|
+
na_rm : bool, default True
|
|
104
|
+
Whether to ignore ``NaN`` values when computing the range.
|
|
105
|
+
|
|
106
|
+
Returns
|
|
107
|
+
-------
|
|
108
|
+
numpy.floating
|
|
109
|
+
Half the sum of the minimum and maximum of *x*.
|
|
110
|
+
"""
|
|
111
|
+
arr = np.asarray(x, dtype=float)
|
|
112
|
+
if na_rm:
|
|
113
|
+
lo, hi = np.nanmin(arr), np.nanmax(arr)
|
|
114
|
+
else:
|
|
115
|
+
lo, hi = np.min(arr), np.max(arr)
|
|
116
|
+
return (lo + hi) / 2.0
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
def _identity(x: Any) -> Any:
|
|
120
|
+
"""Return *x* unchanged (port of R ``force`` used as the default fun).
|
|
121
|
+
|
|
122
|
+
Parameters
|
|
123
|
+
----------
|
|
124
|
+
x : Any
|
|
125
|
+
|
|
126
|
+
Returns
|
|
127
|
+
-------
|
|
128
|
+
Any
|
|
129
|
+
The input, unchanged.
|
|
130
|
+
"""
|
|
131
|
+
return x
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
# ---------------------------------------------------------------------------
|
|
135
|
+
# StatFunxy ggproto
|
|
136
|
+
# ---------------------------------------------------------------------------
|
|
137
|
+
class StatFunxy(Stat):
|
|
138
|
+
"""Apply ``funx``/``funy`` to the ``x``/``y`` positions per group.
|
|
139
|
+
|
|
140
|
+
Mirrors the R ``StatFunxy`` ggproto object. ``compute_group`` calls
|
|
141
|
+
``funx`` on the group's ``x`` values and ``funy`` on its ``y`` values,
|
|
142
|
+
then reconciles the lengths of the remaining columns (cropping or
|
|
143
|
+
recycling) before recombining.
|
|
144
|
+
|
|
145
|
+
Attributes
|
|
146
|
+
----------
|
|
147
|
+
required_aes : list of str
|
|
148
|
+
``['x', 'y']``.
|
|
149
|
+
"""
|
|
150
|
+
|
|
151
|
+
required_aes = ["x", "y"]
|
|
152
|
+
|
|
153
|
+
def compute_group(
|
|
154
|
+
self,
|
|
155
|
+
data: pd.DataFrame,
|
|
156
|
+
scales: Any,
|
|
157
|
+
funx: Callable[..., Any] = _identity,
|
|
158
|
+
funy: Callable[..., Any] = _identity,
|
|
159
|
+
argx: Optional[Dict[str, Any]] = None,
|
|
160
|
+
argy: Optional[Dict[str, Any]] = None,
|
|
161
|
+
crop_other: bool = True,
|
|
162
|
+
) -> pd.DataFrame:
|
|
163
|
+
"""Apply ``funx``/``funy`` to ``x``/``y`` and reconcile lengths.
|
|
164
|
+
|
|
165
|
+
Parameters
|
|
166
|
+
----------
|
|
167
|
+
data : pandas.DataFrame
|
|
168
|
+
One group's data; must contain ``x`` and ``y`` columns.
|
|
169
|
+
scales : Any
|
|
170
|
+
Panel scales (unused; present for signature parity).
|
|
171
|
+
funx, funy : callable
|
|
172
|
+
Functions applied to the ``x`` and ``y`` positions
|
|
173
|
+
respectively. Each is called as ``fun(values, **arg)``.
|
|
174
|
+
argx, argy : dict, optional
|
|
175
|
+
Named keyword arguments forwarded to ``funx`` / ``funy``.
|
|
176
|
+
crop_other : bool, default True
|
|
177
|
+
Whether the remaining (non ``x``/``y``) columns should be
|
|
178
|
+
cropped to the length of the longest of ``funx``/``funy``'s
|
|
179
|
+
results. Set ``False`` when the functions return length-one
|
|
180
|
+
summaries that should be recycled against the full group.
|
|
181
|
+
|
|
182
|
+
Returns
|
|
183
|
+
-------
|
|
184
|
+
pandas.DataFrame
|
|
185
|
+
Columns: the original non ``x``/``y`` columns (in their
|
|
186
|
+
original order) followed by ``x`` and ``y``, each recycled to
|
|
187
|
+
a common length.
|
|
188
|
+
"""
|
|
189
|
+
if argx is None:
|
|
190
|
+
argx = {}
|
|
191
|
+
if argy is None:
|
|
192
|
+
argy = {}
|
|
193
|
+
|
|
194
|
+
# Apply functions. R: do.call(funx, c(unname(data["x"]), argx)),
|
|
195
|
+
# i.e. the column is the first positional argument with its name
|
|
196
|
+
# stripped, followed by the named ``argx`` arguments.
|
|
197
|
+
x = funx(np.asarray(data["x"].to_numpy(), dtype=float), **argx)
|
|
198
|
+
y = funy(np.asarray(data["y"].to_numpy(), dtype=float), **argy)
|
|
199
|
+
x = np.atleast_1d(np.asarray(x))
|
|
200
|
+
y = np.atleast_1d(np.asarray(y))
|
|
201
|
+
|
|
202
|
+
# Ensure the rest of the data is of the correct length.
|
|
203
|
+
other_names = [c for c in data.columns if c not in ("x", "y")]
|
|
204
|
+
size = int(max(len(x), len(y)))
|
|
205
|
+
if crop_other:
|
|
206
|
+
# R: lapply(data[other], `[`, i = size) where size = seq_len(...).
|
|
207
|
+
# Positional crop to the first ``size`` elements (1-based 1:size
|
|
208
|
+
# -> 0-based slice [0:size]).
|
|
209
|
+
other = {c: data[c].to_numpy()[:size] for c in other_names}
|
|
210
|
+
else:
|
|
211
|
+
other = {c: data[c].to_numpy() for c in other_names}
|
|
212
|
+
|
|
213
|
+
# Combine: other columns first, then x, then y (R column order).
|
|
214
|
+
combined: Dict[str, Any] = dict(other)
|
|
215
|
+
combined["x"] = x
|
|
216
|
+
combined["y"] = y
|
|
217
|
+
|
|
218
|
+
# Recycle every column to a common length (length-1 -> longest).
|
|
219
|
+
recycled = vec_recycle_common(*combined.values())
|
|
220
|
+
out = {name: arr for name, arr in zip(combined.keys(), recycled)}
|
|
221
|
+
return data_frame0(**out)
|
|
222
|
+
|
|
223
|
+
|
|
224
|
+
# ---------------------------------------------------------------------------
|
|
225
|
+
# Constructors
|
|
226
|
+
# ---------------------------------------------------------------------------
|
|
227
|
+
def stat_funxy(
|
|
228
|
+
mapping: Optional[Mapping] = None,
|
|
229
|
+
data: Any = None,
|
|
230
|
+
geom: str = "point",
|
|
231
|
+
position: str = "identity",
|
|
232
|
+
*,
|
|
233
|
+
funx: Callable[..., Any] = _identity,
|
|
234
|
+
funy: Callable[..., Any] = _identity,
|
|
235
|
+
argx: Optional[Dict[str, Any]] = None,
|
|
236
|
+
argy: Optional[Dict[str, Any]] = None,
|
|
237
|
+
crop_other: bool = True,
|
|
238
|
+
show_legend: Optional[bool] = None,
|
|
239
|
+
inherit_aes: bool = True,
|
|
240
|
+
**kwargs: Any,
|
|
241
|
+
) -> Any:
|
|
242
|
+
"""Apply a function to a layer's ``x`` and ``y`` position coordinates.
|
|
243
|
+
|
|
244
|
+
Port of R ``stat_funxy``.
|
|
245
|
+
|
|
246
|
+
Parameters
|
|
247
|
+
----------
|
|
248
|
+
mapping : Mapping, optional
|
|
249
|
+
Aesthetic mapping (see :func:`ggplot2_py.aes`).
|
|
250
|
+
data : DataFrame or callable, optional
|
|
251
|
+
Layer data.
|
|
252
|
+
geom : str, default ``"point"``
|
|
253
|
+
Geometry used to render the computed positions.
|
|
254
|
+
position : str, default ``"identity"``
|
|
255
|
+
Position adjustment.
|
|
256
|
+
funx, funy : callable, default identity
|
|
257
|
+
Functions called on the layer's ``x`` and ``y`` positions
|
|
258
|
+
respectively. Default ``force`` (identity) leaves data as-is.
|
|
259
|
+
argx, argy : dict, optional
|
|
260
|
+
Named arguments forwarded to ``funx`` / ``funy``. Default empty.
|
|
261
|
+
crop_other : bool, default True
|
|
262
|
+
Whether the other data should be fitted to the length of ``x`` and
|
|
263
|
+
``y``. Set ``False`` when ``funx``/``funy`` compute length-one
|
|
264
|
+
summaries that need to be recycled.
|
|
265
|
+
show_legend : bool, optional
|
|
266
|
+
Whether to include this layer in the legend.
|
|
267
|
+
inherit_aes : bool, default True
|
|
268
|
+
Whether to inherit the plot-level mapping.
|
|
269
|
+
**kwargs
|
|
270
|
+
Additional parameters forwarded to the layer.
|
|
271
|
+
|
|
272
|
+
Returns
|
|
273
|
+
-------
|
|
274
|
+
ggplot2_py.Layer
|
|
275
|
+
A layer backed by :class:`StatFunxy`.
|
|
276
|
+
|
|
277
|
+
Raises
|
|
278
|
+
------
|
|
279
|
+
ValueError
|
|
280
|
+
If ``funx``/``funy`` are not callable, if ``argx``/``argy`` are not
|
|
281
|
+
dicts, or if ``argx``/``argy`` contain unnamed (empty-string-key)
|
|
282
|
+
elements.
|
|
283
|
+
"""
|
|
284
|
+
if argx is None:
|
|
285
|
+
argx = {}
|
|
286
|
+
if argy is None:
|
|
287
|
+
argy = {}
|
|
288
|
+
|
|
289
|
+
# stopifnot(...) validations from R, translated to cli_abort.
|
|
290
|
+
if not callable(funx):
|
|
291
|
+
cli_abort("The `funx` argument must be a function.")
|
|
292
|
+
if not callable(funy):
|
|
293
|
+
cli_abort("The `funy` argument must be a function.")
|
|
294
|
+
if not isinstance(argx, dict) or not isinstance(argy, dict):
|
|
295
|
+
cli_abort("The `argx` and `argy` arguments must be lists.")
|
|
296
|
+
# R: length(argx) == sum(nzchar(names(argx))) -- every element named.
|
|
297
|
+
if any((not isinstance(k, str)) or k == "" for k in argx.keys()):
|
|
298
|
+
cli_abort("The `argx` list must have named elements")
|
|
299
|
+
if any((not isinstance(k, str)) or k == "" for k in argy.keys()):
|
|
300
|
+
cli_abort("The `argy` list must have named elements")
|
|
301
|
+
|
|
302
|
+
return _layer(
|
|
303
|
+
data=data,
|
|
304
|
+
mapping=mapping,
|
|
305
|
+
stat=StatFunxy,
|
|
306
|
+
geom=geom,
|
|
307
|
+
position=position,
|
|
308
|
+
show_legend=show_legend,
|
|
309
|
+
inherit_aes=inherit_aes,
|
|
310
|
+
params={
|
|
311
|
+
"funx": funx,
|
|
312
|
+
"funy": funy,
|
|
313
|
+
"argx": argx,
|
|
314
|
+
"argy": argy,
|
|
315
|
+
"crop_other": crop_other,
|
|
316
|
+
**kwargs,
|
|
317
|
+
},
|
|
318
|
+
)
|
|
319
|
+
|
|
320
|
+
|
|
321
|
+
def stat_centroid(
|
|
322
|
+
mapping: Optional[Mapping] = None,
|
|
323
|
+
data: Any = None,
|
|
324
|
+
geom: str = "point",
|
|
325
|
+
position: str = "identity",
|
|
326
|
+
*,
|
|
327
|
+
funx: Callable[..., Any] = _mean,
|
|
328
|
+
funy: Callable[..., Any] = _mean,
|
|
329
|
+
argx: Optional[Dict[str, Any]] = None,
|
|
330
|
+
argy: Optional[Dict[str, Any]] = None,
|
|
331
|
+
crop_other: bool = True,
|
|
332
|
+
show_legend: Optional[bool] = None,
|
|
333
|
+
inherit_aes: bool = True,
|
|
334
|
+
**kwargs: Any,
|
|
335
|
+
) -> Any:
|
|
336
|
+
"""Compute group centroids (means of ``x`` and ``y``).
|
|
337
|
+
|
|
338
|
+
Convenience wrapper around :func:`stat_funxy` with ``funx = funy =
|
|
339
|
+
mean`` and ``argx = argy = {'na_rm': True}`` (port of R
|
|
340
|
+
``stat_centroid``).
|
|
341
|
+
|
|
342
|
+
Parameters
|
|
343
|
+
----------
|
|
344
|
+
mapping : Mapping, optional
|
|
345
|
+
data : DataFrame or callable, optional
|
|
346
|
+
geom : str, default ``"point"``
|
|
347
|
+
position : str, default ``"identity"``
|
|
348
|
+
funx, funy : callable, default NaN-aware mean
|
|
349
|
+
Functions applied to ``x`` / ``y``.
|
|
350
|
+
argx, argy : dict, optional
|
|
351
|
+
Named arguments forwarded to ``funx`` / ``funy``. Default
|
|
352
|
+
``{'na_rm': True}``.
|
|
353
|
+
crop_other : bool, default True
|
|
354
|
+
show_legend : bool, optional
|
|
355
|
+
inherit_aes : bool, default True
|
|
356
|
+
**kwargs
|
|
357
|
+
|
|
358
|
+
Returns
|
|
359
|
+
-------
|
|
360
|
+
ggplot2_py.Layer
|
|
361
|
+
"""
|
|
362
|
+
if argx is None:
|
|
363
|
+
argx = {"na_rm": True}
|
|
364
|
+
if argy is None:
|
|
365
|
+
argy = {"na_rm": True}
|
|
366
|
+
return stat_funxy(
|
|
367
|
+
mapping=mapping,
|
|
368
|
+
data=data,
|
|
369
|
+
geom=geom,
|
|
370
|
+
position=position,
|
|
371
|
+
funx=funx,
|
|
372
|
+
funy=funy,
|
|
373
|
+
argx=argx,
|
|
374
|
+
argy=argy,
|
|
375
|
+
crop_other=crop_other,
|
|
376
|
+
show_legend=show_legend,
|
|
377
|
+
inherit_aes=inherit_aes,
|
|
378
|
+
**kwargs,
|
|
379
|
+
)
|
|
380
|
+
|
|
381
|
+
|
|
382
|
+
def stat_midpoint(
|
|
383
|
+
mapping: Optional[Mapping] = None,
|
|
384
|
+
data: Any = None,
|
|
385
|
+
geom: str = "point",
|
|
386
|
+
position: str = "identity",
|
|
387
|
+
*,
|
|
388
|
+
argx: Optional[Dict[str, Any]] = None,
|
|
389
|
+
argy: Optional[Dict[str, Any]] = None,
|
|
390
|
+
crop_other: bool = True,
|
|
391
|
+
show_legend: Optional[bool] = None,
|
|
392
|
+
inherit_aes: bool = True,
|
|
393
|
+
**kwargs: Any,
|
|
394
|
+
) -> Any:
|
|
395
|
+
"""Compute group midpoints (``(min + max) / 2`` of ``x`` and ``y``).
|
|
396
|
+
|
|
397
|
+
Convenience wrapper around :func:`stat_funxy` whose ``funx``/``funy``
|
|
398
|
+
is the closure ``sum(range(x, na.rm)) / 2`` (port of R
|
|
399
|
+
``stat_midpoint``).
|
|
400
|
+
|
|
401
|
+
Parameters
|
|
402
|
+
----------
|
|
403
|
+
mapping : Mapping, optional
|
|
404
|
+
data : DataFrame or callable, optional
|
|
405
|
+
geom : str, default ``"point"``
|
|
406
|
+
position : str, default ``"identity"``
|
|
407
|
+
argx, argy : dict, optional
|
|
408
|
+
Named arguments forwarded to the midpoint function. Default
|
|
409
|
+
``{'na_rm': True}``.
|
|
410
|
+
crop_other : bool, default True
|
|
411
|
+
show_legend : bool, optional
|
|
412
|
+
inherit_aes : bool, default True
|
|
413
|
+
**kwargs
|
|
414
|
+
|
|
415
|
+
Returns
|
|
416
|
+
-------
|
|
417
|
+
ggplot2_py.Layer
|
|
418
|
+
"""
|
|
419
|
+
if argx is None:
|
|
420
|
+
argx = {"na_rm": True}
|
|
421
|
+
if argy is None:
|
|
422
|
+
argy = {"na_rm": True}
|
|
423
|
+
return stat_funxy(
|
|
424
|
+
mapping=mapping,
|
|
425
|
+
data=data,
|
|
426
|
+
geom=geom,
|
|
427
|
+
position=position,
|
|
428
|
+
funx=_midpoint,
|
|
429
|
+
funy=_midpoint,
|
|
430
|
+
argx=argx,
|
|
431
|
+
argy=argy,
|
|
432
|
+
crop_other=crop_other,
|
|
433
|
+
show_legend=show_legend,
|
|
434
|
+
inherit_aes=inherit_aes,
|
|
435
|
+
**kwargs,
|
|
436
|
+
)
|