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.
- plotnine/__init__.py +2 -0
- plotnine/_mpl/layout_manager/_engine.py +1 -1
- plotnine/_mpl/layout_manager/_layout_items.py +126 -41
- plotnine/_mpl/layout_manager/_layout_tree.py +712 -314
- plotnine/_mpl/layout_manager/_spaces.py +305 -101
- plotnine/_mpl/patches.py +70 -34
- plotnine/_mpl/text.py +144 -63
- plotnine/_mpl/utils.py +1 -1
- plotnine/_utils/__init__.py +50 -107
- plotnine/_utils/context.py +78 -2
- plotnine/_utils/ipython.py +35 -51
- plotnine/_utils/quarto.py +26 -0
- plotnine/_utils/yippie.py +115 -0
- plotnine/composition/__init__.py +11 -0
- plotnine/composition/_beside.py +55 -0
- plotnine/composition/_compose.py +471 -0
- plotnine/composition/_plot_spacer.py +60 -0
- plotnine/composition/_stack.py +55 -0
- plotnine/coords/coord.py +3 -3
- plotnine/data/__init__.py +31 -0
- plotnine/data/anscombe-quartet.csv +45 -0
- plotnine/doctools.py +4 -4
- plotnine/facets/facet.py +4 -4
- plotnine/facets/strips.py +17 -28
- plotnine/geoms/annotate.py +13 -13
- plotnine/geoms/annotation_logticks.py +7 -8
- plotnine/geoms/annotation_stripes.py +6 -6
- plotnine/geoms/geom.py +60 -27
- plotnine/geoms/geom_abline.py +3 -2
- plotnine/geoms/geom_area.py +2 -2
- plotnine/geoms/geom_bar.py +1 -0
- plotnine/geoms/geom_bin_2d.py +6 -2
- plotnine/geoms/geom_blank.py +0 -3
- plotnine/geoms/geom_boxplot.py +8 -4
- plotnine/geoms/geom_col.py +2 -2
- plotnine/geoms/geom_count.py +6 -2
- plotnine/geoms/geom_crossbar.py +3 -3
- plotnine/geoms/geom_density_2d.py +6 -2
- plotnine/geoms/geom_dotplot.py +2 -2
- plotnine/geoms/geom_errorbar.py +2 -2
- plotnine/geoms/geom_errorbarh.py +2 -2
- plotnine/geoms/geom_histogram.py +1 -1
- plotnine/geoms/geom_hline.py +3 -2
- plotnine/geoms/geom_linerange.py +2 -2
- plotnine/geoms/geom_map.py +5 -5
- plotnine/geoms/geom_path.py +11 -12
- plotnine/geoms/geom_point.py +4 -5
- plotnine/geoms/geom_pointdensity.py +4 -0
- plotnine/geoms/geom_pointrange.py +3 -5
- plotnine/geoms/geom_polygon.py +2 -3
- plotnine/geoms/geom_qq.py +4 -0
- plotnine/geoms/geom_qq_line.py +4 -0
- plotnine/geoms/geom_quantile.py +4 -0
- plotnine/geoms/geom_raster.py +4 -5
- plotnine/geoms/geom_rect.py +3 -4
- plotnine/geoms/geom_ribbon.py +7 -7
- plotnine/geoms/geom_rug.py +1 -1
- plotnine/geoms/geom_segment.py +2 -2
- plotnine/geoms/geom_sina.py +3 -3
- plotnine/geoms/geom_smooth.py +7 -3
- plotnine/geoms/geom_step.py +2 -2
- plotnine/geoms/geom_text.py +2 -3
- plotnine/geoms/geom_violin.py +8 -5
- plotnine/geoms/geom_vline.py +3 -2
- plotnine/ggplot.py +64 -85
- plotnine/guides/guide.py +7 -10
- plotnine/guides/guide_colorbar.py +3 -3
- plotnine/guides/guide_legend.py +3 -3
- plotnine/guides/guides.py +6 -6
- plotnine/helpers.py +49 -0
- plotnine/iapi.py +28 -5
- plotnine/labels.py +3 -3
- plotnine/layer.py +36 -19
- plotnine/mapping/_atomic.py +178 -0
- plotnine/mapping/_env.py +13 -2
- plotnine/mapping/_eval_environment.py +1 -1
- plotnine/mapping/aes.py +85 -49
- plotnine/scales/__init__.py +2 -0
- plotnine/scales/limits.py +7 -7
- plotnine/scales/scale.py +3 -3
- plotnine/scales/scale_color.py +82 -18
- plotnine/scales/scale_continuous.py +6 -4
- plotnine/scales/scale_datetime.py +28 -14
- plotnine/scales/scale_discrete.py +1 -1
- plotnine/scales/scale_identity.py +21 -2
- plotnine/scales/scale_manual.py +8 -2
- plotnine/scales/scale_xy.py +2 -2
- plotnine/stats/binning.py +4 -1
- plotnine/stats/smoothers.py +23 -36
- plotnine/stats/stat.py +20 -32
- plotnine/stats/stat_bin.py +6 -5
- plotnine/stats/stat_bin_2d.py +11 -9
- plotnine/stats/stat_bindot.py +13 -16
- plotnine/stats/stat_boxplot.py +6 -6
- plotnine/stats/stat_count.py +6 -9
- plotnine/stats/stat_density.py +7 -10
- plotnine/stats/stat_density_2d.py +12 -8
- plotnine/stats/stat_ecdf.py +7 -6
- plotnine/stats/stat_ellipse.py +9 -6
- plotnine/stats/stat_function.py +10 -8
- plotnine/stats/stat_hull.py +6 -3
- plotnine/stats/stat_identity.py +5 -2
- plotnine/stats/stat_pointdensity.py +5 -7
- plotnine/stats/stat_qq.py +46 -20
- plotnine/stats/stat_qq_line.py +16 -11
- plotnine/stats/stat_quantile.py +15 -9
- plotnine/stats/stat_sina.py +13 -15
- plotnine/stats/stat_smooth.py +8 -10
- plotnine/stats/stat_sum.py +5 -2
- plotnine/stats/stat_summary.py +7 -10
- plotnine/stats/stat_summary_bin.py +11 -14
- plotnine/stats/stat_unique.py +5 -2
- plotnine/stats/stat_ydensity.py +8 -11
- plotnine/themes/elements/__init__.py +2 -1
- plotnine/themes/elements/element_line.py +17 -9
- plotnine/themes/elements/margin.py +64 -1
- plotnine/themes/theme.py +9 -1
- plotnine/themes/theme_538.py +0 -1
- plotnine/themes/theme_bw.py +0 -1
- plotnine/themes/theme_dark.py +0 -1
- plotnine/themes/theme_gray.py +6 -5
- plotnine/themes/theme_light.py +1 -1
- plotnine/themes/theme_matplotlib.py +5 -5
- plotnine/themes/theme_seaborn.py +7 -4
- plotnine/themes/theme_void.py +9 -8
- plotnine/themes/theme_xkcd.py +0 -1
- plotnine/themes/themeable.py +109 -31
- plotnine/typing.py +17 -6
- plotnine/watermark.py +3 -3
- {plotnine-0.15.0.dev3.dist-info → plotnine-0.15.2.dist-info}/METADATA +13 -6
- plotnine-0.15.2.dist-info/RECORD +221 -0
- {plotnine-0.15.0.dev3.dist-info → plotnine-0.15.2.dist-info}/WHEEL +1 -1
- plotnine/plot_composition/__init__.py +0 -10
- plotnine/plot_composition/_compose.py +0 -436
- plotnine/plot_composition/_spacer.py +0 -32
- plotnine-0.15.0.dev3.dist-info/RECORD +0 -215
- /plotnine/{plot_composition → composition}/_plotspec.py +0 -0
- {plotnine-0.15.0.dev3.dist-info → plotnine-0.15.2.dist-info}/licenses/LICENSE +0 -0
- {plotnine-0.15.0.dev3.dist-info → plotnine-0.15.2.dist-info}/top_level.txt +0 -0
plotnine/stats/stat_qq.py
CHANGED
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from typing import TYPE_CHECKING
|
|
4
|
+
|
|
1
5
|
import numpy as np
|
|
2
6
|
import pandas as pd
|
|
3
7
|
|
|
@@ -6,6 +10,11 @@ from ..exceptions import PlotnineError
|
|
|
6
10
|
from ..mapping.evaluation import after_stat
|
|
7
11
|
from .stat import stat
|
|
8
12
|
|
|
13
|
+
if TYPE_CHECKING:
|
|
14
|
+
from typing import Any, Sequence
|
|
15
|
+
|
|
16
|
+
from plotnine.typing import FloatArray
|
|
17
|
+
|
|
9
18
|
|
|
10
19
|
# Note: distribution should be a name from scipy.stat.distribution
|
|
11
20
|
@document
|
|
@@ -38,6 +47,7 @@ class stat_qq(stat):
|
|
|
38
47
|
|
|
39
48
|
See Also
|
|
40
49
|
--------
|
|
50
|
+
plotnine.geom_qq : The default `geom` for this `stat`.
|
|
41
51
|
scipy.stats.mstats.plotting_positions : Uses `alpha_beta`
|
|
42
52
|
to calculate the quantiles.
|
|
43
53
|
"""
|
|
@@ -65,25 +75,41 @@ class stat_qq(stat):
|
|
|
65
75
|
"alpha_beta": (3 / 8, 3 / 8),
|
|
66
76
|
}
|
|
67
77
|
|
|
68
|
-
|
|
69
|
-
def compute_group(cls, data, scales, **params):
|
|
70
|
-
from scipy.stats.mstats import plotting_positions
|
|
71
|
-
|
|
72
|
-
from .distributions import get_continuous_distribution
|
|
73
|
-
|
|
78
|
+
def compute_group(self, data, scales):
|
|
74
79
|
sample = data["sample"].sort_values().to_numpy()
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
"the number of sample values."
|
|
84
|
-
)
|
|
85
|
-
|
|
86
|
-
quantiles = np.asarray(quantiles)
|
|
87
|
-
cdist = get_continuous_distribution(params["distribution"])
|
|
88
|
-
theoretical = cdist.ppf(quantiles, **params["dparams"])
|
|
80
|
+
theoretical = theoretical_qq(
|
|
81
|
+
sample,
|
|
82
|
+
self.params["distribution"],
|
|
83
|
+
alpha=self.params["alpha_beta"][0],
|
|
84
|
+
beta=self.params["alpha_beta"][1],
|
|
85
|
+
quantiles=self.params["quantiles"],
|
|
86
|
+
distribution_params=self.params["dparams"],
|
|
87
|
+
)
|
|
89
88
|
return pd.DataFrame({"sample": sample, "theoretical": theoretical})
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
def theoretical_qq(
|
|
92
|
+
x: FloatArray,
|
|
93
|
+
distribution: str,
|
|
94
|
+
alpha: float,
|
|
95
|
+
beta: float,
|
|
96
|
+
quantiles: Sequence[float] | None,
|
|
97
|
+
distribution_params: dict[str, Any],
|
|
98
|
+
) -> FloatArray:
|
|
99
|
+
"""
|
|
100
|
+
Caculate theoretical qq distribution
|
|
101
|
+
"""
|
|
102
|
+
from scipy.stats.mstats import plotting_positions
|
|
103
|
+
|
|
104
|
+
from .distributions import get_continuous_distribution
|
|
105
|
+
|
|
106
|
+
if quantiles is None:
|
|
107
|
+
quantiles = plotting_positions(x, alpha, beta)
|
|
108
|
+
elif len(quantiles) != len(x):
|
|
109
|
+
raise PlotnineError(
|
|
110
|
+
"The number of quantile values is not the same as "
|
|
111
|
+
"the number of sample values."
|
|
112
|
+
)
|
|
113
|
+
|
|
114
|
+
cdist = get_continuous_distribution(distribution)
|
|
115
|
+
return cdist.ppf(np.asarray(quantiles), **distribution_params)
|
plotnine/stats/stat_qq_line.py
CHANGED
|
@@ -4,7 +4,7 @@ import pandas as pd
|
|
|
4
4
|
from ..doctools import document
|
|
5
5
|
from ..exceptions import PlotnineError
|
|
6
6
|
from .stat import stat
|
|
7
|
-
from .stat_qq import
|
|
7
|
+
from .stat_qq import theoretical_qq
|
|
8
8
|
|
|
9
9
|
|
|
10
10
|
@document
|
|
@@ -41,6 +41,7 @@ class stat_qq_line(stat):
|
|
|
41
41
|
|
|
42
42
|
See Also
|
|
43
43
|
--------
|
|
44
|
+
plotnine.geom_qq_line : The default `geom` for this `stat`.
|
|
44
45
|
scipy.stats.mstats.plotting_positions : Uses `alpha_beta`
|
|
45
46
|
to calculate the quantiles.
|
|
46
47
|
"""
|
|
@@ -64,31 +65,35 @@ class stat_qq_line(stat):
|
|
|
64
65
|
raise PlotnineError(
|
|
65
66
|
"Cannot fit line quantiles. 'line_p' must be of length 2"
|
|
66
67
|
)
|
|
67
|
-
return self.params
|
|
68
68
|
|
|
69
|
-
|
|
70
|
-
def compute_group(cls, data, scales, **params):
|
|
69
|
+
def compute_group(self, data, scales):
|
|
71
70
|
from scipy.stats.mstats import mquantiles
|
|
72
71
|
|
|
73
72
|
from .distributions import get_continuous_distribution
|
|
74
73
|
|
|
75
|
-
line_p = params["line_p"]
|
|
76
|
-
dparams = params["dparams"]
|
|
74
|
+
line_p = self.params["line_p"]
|
|
75
|
+
dparams = self.params["dparams"]
|
|
77
76
|
|
|
78
77
|
# Compute theoretical values
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
78
|
+
sample = data["sample"].sort_values().to_numpy()
|
|
79
|
+
theoretical = theoretical_qq(
|
|
80
|
+
sample,
|
|
81
|
+
self.params["distribution"],
|
|
82
|
+
alpha=self.params["alpha_beta"][0],
|
|
83
|
+
beta=self.params["alpha_beta"][1],
|
|
84
|
+
quantiles=self.params["quantiles"],
|
|
85
|
+
distribution_params=dparams,
|
|
86
|
+
)
|
|
82
87
|
|
|
83
88
|
# Compute slope & intercept of the line through the quantiles
|
|
84
|
-
cdist = get_continuous_distribution(params["distribution"])
|
|
89
|
+
cdist = get_continuous_distribution(self.params["distribution"])
|
|
85
90
|
x_coords = cdist.ppf(line_p, **dparams)
|
|
86
91
|
y_coords = mquantiles(sample, line_p)
|
|
87
92
|
slope = (np.diff(y_coords) / np.diff(x_coords))[0]
|
|
88
93
|
intercept = y_coords[0] - slope * x_coords[0]
|
|
89
94
|
|
|
90
95
|
# Get x,y points that describe the line
|
|
91
|
-
if params["fullrange"] and scales.x:
|
|
96
|
+
if self.params["fullrange"] and scales.x:
|
|
92
97
|
x = scales.x.dimension()
|
|
93
98
|
else:
|
|
94
99
|
x = theoretical.min(), theoretical.max()
|
plotnine/stats/stat_quantile.py
CHANGED
|
@@ -29,8 +29,8 @@ class stat_quantile(stat):
|
|
|
29
29
|
|
|
30
30
|
See Also
|
|
31
31
|
--------
|
|
32
|
+
plotnine.geom_quantile : The default `geom` for this `stat`.
|
|
32
33
|
statsmodels.regression.quantile_regression.QuantReg
|
|
33
|
-
plotnine.geom_quantile
|
|
34
34
|
"""
|
|
35
35
|
|
|
36
36
|
_aesthetics_doc = """
|
|
@@ -59,30 +59,36 @@ class stat_quantile(stat):
|
|
|
59
59
|
CREATES = {"quantile", "group"}
|
|
60
60
|
|
|
61
61
|
def setup_params(self, data):
|
|
62
|
-
params = self.params
|
|
62
|
+
params = self.params
|
|
63
63
|
if params["formula"] is None:
|
|
64
64
|
params["formula"] = "y ~ x"
|
|
65
65
|
warn("Formula not specified, using '{}'", PlotnineWarning)
|
|
66
|
+
else:
|
|
67
|
+
params["eval_env"] = self.environment.to_patsy_env()
|
|
68
|
+
|
|
66
69
|
try:
|
|
67
70
|
iter(params["quantiles"])
|
|
68
71
|
except TypeError:
|
|
69
72
|
params["quantiles"] = (params["quantiles"],)
|
|
70
73
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
res = [quant_pred(q, data, **params) for q in params["quantiles"]]
|
|
74
|
+
def compute_group(self, data, scales):
|
|
75
|
+
res = [
|
|
76
|
+
quant_pred(q, data, self.params) for q in self.params["quantiles"]
|
|
77
|
+
]
|
|
76
78
|
return pd.concat(res, axis=0, ignore_index=True)
|
|
77
79
|
|
|
78
80
|
|
|
79
|
-
def quant_pred(q, data,
|
|
81
|
+
def quant_pred(q, data, params):
|
|
80
82
|
"""
|
|
81
83
|
Quantile precitions
|
|
82
84
|
"""
|
|
83
85
|
import statsmodels.formula.api as smf
|
|
84
86
|
|
|
85
|
-
mod = smf.quantreg(
|
|
87
|
+
mod = smf.quantreg(
|
|
88
|
+
params["formula"],
|
|
89
|
+
data,
|
|
90
|
+
eval_env=params.get("eval_env"),
|
|
91
|
+
)
|
|
86
92
|
reg_res = mod.fit(q=q, **params["method_args"])
|
|
87
93
|
out = pd.DataFrame(
|
|
88
94
|
{
|
plotnine/stats/stat_sina.py
CHANGED
|
@@ -69,7 +69,7 @@ class stat_sina(stat):
|
|
|
69
69
|
|
|
70
70
|
See Also
|
|
71
71
|
--------
|
|
72
|
-
plotnine.geom_sina
|
|
72
|
+
plotnine.geom_sina : The default `geom` for this `stat`.
|
|
73
73
|
"""
|
|
74
74
|
|
|
75
75
|
_aesthetics_doc = """
|
|
@@ -116,7 +116,7 @@ class stat_sina(stat):
|
|
|
116
116
|
return data
|
|
117
117
|
|
|
118
118
|
def setup_params(self, data):
|
|
119
|
-
params = self.params
|
|
119
|
+
params = self.params
|
|
120
120
|
random_state = params["random_state"]
|
|
121
121
|
|
|
122
122
|
if params["maxwidth"] is None:
|
|
@@ -137,10 +137,9 @@ class stat_sina(stat):
|
|
|
137
137
|
params["clip"] = (-np.inf, np.inf)
|
|
138
138
|
params["bounds"] = (-np.inf, np.inf)
|
|
139
139
|
params["n"] = 512
|
|
140
|
-
return params
|
|
141
140
|
|
|
142
|
-
|
|
143
|
-
|
|
141
|
+
def compute_panel(self, data, scales):
|
|
142
|
+
params = self.params
|
|
144
143
|
maxwidth = params["maxwidth"]
|
|
145
144
|
random_state = params["random_state"]
|
|
146
145
|
fuzz = 1e-8
|
|
@@ -154,7 +153,7 @@ class stat_sina(stat):
|
|
|
154
153
|
else:
|
|
155
154
|
params["bins"] = breaks_from_bins(y_dim_fuzzed, params["bins"])
|
|
156
155
|
|
|
157
|
-
data = super(
|
|
156
|
+
data = super().compute_panel(data, scales)
|
|
158
157
|
|
|
159
158
|
if not len(data):
|
|
160
159
|
return data
|
|
@@ -198,11 +197,10 @@ class stat_sina(stat):
|
|
|
198
197
|
|
|
199
198
|
return data
|
|
200
199
|
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
bin_limit = params["bin_limit"]
|
|
200
|
+
def compute_group(self, data, scales):
|
|
201
|
+
maxwidth = self.params["maxwidth"]
|
|
202
|
+
bins = self.params["bins"]
|
|
203
|
+
bin_limit = self.params["bin_limit"]
|
|
206
204
|
weight = None
|
|
207
205
|
y = data["y"]
|
|
208
206
|
|
|
@@ -215,12 +213,12 @@ class stat_sina(stat):
|
|
|
215
213
|
elif len(np.unique(y)) < 2:
|
|
216
214
|
data["density"] = 1
|
|
217
215
|
data["scaled"] = 1
|
|
218
|
-
elif params["method"] == "density":
|
|
216
|
+
elif self.params["method"] == "density":
|
|
219
217
|
from scipy.interpolate import interp1d
|
|
220
218
|
|
|
221
219
|
# density kernel estimation
|
|
222
220
|
range_y = y.min(), y.max()
|
|
223
|
-
dens = compute_density(y, weight, range_y,
|
|
221
|
+
dens = compute_density(y, weight, range_y, self.params)
|
|
224
222
|
densf = interp1d(
|
|
225
223
|
dens["x"],
|
|
226
224
|
dens["density"],
|
|
@@ -253,9 +251,9 @@ class stat_sina(stat):
|
|
|
253
251
|
|
|
254
252
|
return data
|
|
255
253
|
|
|
256
|
-
def finish_layer(self, data
|
|
254
|
+
def finish_layer(self, data):
|
|
257
255
|
# Rescale x in case positions have been adjusted
|
|
258
|
-
style = params["style"]
|
|
256
|
+
style = self.params["style"]
|
|
259
257
|
x_mean = data["x"].to_numpy()
|
|
260
258
|
x_mod = (data["xmax"] - data["xmin"]) / data["width"]
|
|
261
259
|
data["x"] = data["x"] + data["x_diff"] * x_mod
|
plotnine/stats/stat_smooth.py
CHANGED
|
@@ -37,7 +37,7 @@ class stat_smooth(stat):
|
|
|
37
37
|
If a `callable` is passed, it must have the signature:
|
|
38
38
|
|
|
39
39
|
```python
|
|
40
|
-
def my_smoother(data, xseq,
|
|
40
|
+
def my_smoother(data, xseq, params):
|
|
41
41
|
# * data - has the x and y values for the model
|
|
42
42
|
# * xseq - x values to be predicted
|
|
43
43
|
# * params - stat parameters
|
|
@@ -106,6 +106,7 @@ class stat_smooth(stat):
|
|
|
106
106
|
|
|
107
107
|
See Also
|
|
108
108
|
--------
|
|
109
|
+
plotnine.geom_smooth : The default `geom` for this `stat`.
|
|
109
110
|
statsmodels.regression.linear_model.OLS
|
|
110
111
|
statsmodels.regression.linear_model.WLS
|
|
111
112
|
statsmodels.robust.robust_linear_model.RLM
|
|
@@ -163,7 +164,7 @@ class stat_smooth(stat):
|
|
|
163
164
|
return data
|
|
164
165
|
|
|
165
166
|
def setup_params(self, data):
|
|
166
|
-
params = self.params
|
|
167
|
+
params = self.params
|
|
167
168
|
# Use loess/lowess for small datasets
|
|
168
169
|
# and glm for large
|
|
169
170
|
if params["method"] == "auto":
|
|
@@ -202,12 +203,9 @@ class stat_smooth(stat):
|
|
|
202
203
|
)
|
|
203
204
|
params["environment"] = self.environment
|
|
204
205
|
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
@classmethod
|
|
208
|
-
def compute_group(cls, data, scales, **params):
|
|
206
|
+
def compute_group(self, data, scales):
|
|
209
207
|
data = data.sort_values("x")
|
|
210
|
-
n = params["n"]
|
|
208
|
+
n = self.params["n"]
|
|
211
209
|
|
|
212
210
|
x_unique = data["x"].unique()
|
|
213
211
|
|
|
@@ -223,15 +221,15 @@ class stat_smooth(stat):
|
|
|
223
221
|
return pd.DataFrame()
|
|
224
222
|
|
|
225
223
|
if data["x"].dtype.kind == "i":
|
|
226
|
-
if params["fullrange"]:
|
|
224
|
+
if self.params["fullrange"]:
|
|
227
225
|
xseq = scales.x.dimension()
|
|
228
226
|
else:
|
|
229
227
|
xseq = np.sort(x_unique)
|
|
230
228
|
else:
|
|
231
|
-
if params["fullrange"]:
|
|
229
|
+
if self.params["fullrange"]:
|
|
232
230
|
rangee = scales.x.dimension()
|
|
233
231
|
else:
|
|
234
232
|
rangee = [data["x"].min(), data["x"].max()]
|
|
235
233
|
xseq = np.linspace(rangee[0], rangee[1], n)
|
|
236
234
|
|
|
237
|
-
return predictdf(data, xseq,
|
|
235
|
+
return predictdf(data, xseq, self.params)
|
plotnine/stats/stat_sum.py
CHANGED
|
@@ -17,6 +17,10 @@ class stat_sum(stat):
|
|
|
17
17
|
Parameters
|
|
18
18
|
----------
|
|
19
19
|
{common_parameters}
|
|
20
|
+
|
|
21
|
+
See Also
|
|
22
|
+
--------
|
|
23
|
+
plotnine.geom_point : The default `geom` for this `stat`.
|
|
20
24
|
"""
|
|
21
25
|
|
|
22
26
|
_aesthetics_doc = """
|
|
@@ -35,8 +39,7 @@ class stat_sum(stat):
|
|
|
35
39
|
DEFAULT_AES = {"size": after_stat("n"), "weight": 1}
|
|
36
40
|
CREATES = {"n", "prop"}
|
|
37
41
|
|
|
38
|
-
|
|
39
|
-
def compute_panel(cls, data, scales, **params):
|
|
42
|
+
def compute_panel(self, data, scales):
|
|
40
43
|
if "weight" not in data:
|
|
41
44
|
data["weight"] = 1
|
|
42
45
|
|
plotnine/stats/stat_summary.py
CHANGED
|
@@ -247,7 +247,7 @@ class stat_summary(stat):
|
|
|
247
247
|
|
|
248
248
|
See Also
|
|
249
249
|
--------
|
|
250
|
-
plotnine.geom_pointrange
|
|
250
|
+
plotnine.geom_pointrange : The default `geom` for this `stat`.
|
|
251
251
|
"""
|
|
252
252
|
|
|
253
253
|
_aesthetics_doc = """
|
|
@@ -299,16 +299,13 @@ class stat_summary(stat):
|
|
|
299
299
|
|
|
300
300
|
self.params["fun_args"]["random_state"] = random_state
|
|
301
301
|
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
@classmethod
|
|
305
|
-
def compute_panel(cls, data, scales, **params):
|
|
302
|
+
def compute_panel(self, data, scales):
|
|
306
303
|
func = make_summary_fun(
|
|
307
|
-
params["fun_data"],
|
|
308
|
-
params["fun_y"],
|
|
309
|
-
params["fun_ymin"],
|
|
310
|
-
params["fun_ymax"],
|
|
311
|
-
params["fun_args"],
|
|
304
|
+
self.params["fun_data"],
|
|
305
|
+
self.params["fun_y"],
|
|
306
|
+
self.params["fun_ymin"],
|
|
307
|
+
self.params["fun_ymax"],
|
|
308
|
+
self.params["fun_args"],
|
|
312
309
|
)
|
|
313
310
|
|
|
314
311
|
# break a dataframe into pieces, summarise each piece,
|
|
@@ -63,7 +63,7 @@ class stat_summary_bin(stat):
|
|
|
63
63
|
|
|
64
64
|
See Also
|
|
65
65
|
--------
|
|
66
|
-
plotnine.geom_pointrange
|
|
66
|
+
plotnine.geom_pointrange : The default `geom` for this `stat`.
|
|
67
67
|
"""
|
|
68
68
|
|
|
69
69
|
_aesthetics_doc = """
|
|
@@ -123,21 +123,18 @@ class stat_summary_bin(stat):
|
|
|
123
123
|
|
|
124
124
|
self.params["fun_args"]["random_state"] = random_state
|
|
125
125
|
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
breaks = params["breaks"]
|
|
132
|
-
binwidth = params["binwidth"]
|
|
133
|
-
boundary = params["boundary"]
|
|
126
|
+
def compute_group(self, data, scales):
|
|
127
|
+
bins = self.params["bins"]
|
|
128
|
+
breaks = self.params["breaks"]
|
|
129
|
+
binwidth = self.params["binwidth"]
|
|
130
|
+
boundary = self.params["boundary"]
|
|
134
131
|
|
|
135
132
|
func = make_summary_fun(
|
|
136
|
-
params["fun_data"],
|
|
137
|
-
params["fun_y"],
|
|
138
|
-
params["fun_ymin"],
|
|
139
|
-
params["fun_ymax"],
|
|
140
|
-
params["fun_args"],
|
|
133
|
+
self.params["fun_data"],
|
|
134
|
+
self.params["fun_y"],
|
|
135
|
+
self.params["fun_ymin"],
|
|
136
|
+
self.params["fun_ymax"],
|
|
137
|
+
self.params["fun_args"],
|
|
141
138
|
)
|
|
142
139
|
|
|
143
140
|
breaks = fuzzybreaks(scales.x, breaks, boundary, binwidth, bins)
|
plotnine/stats/stat_unique.py
CHANGED
|
@@ -12,10 +12,13 @@ class stat_unique(stat):
|
|
|
12
12
|
Parameters
|
|
13
13
|
----------
|
|
14
14
|
{common_parameters}
|
|
15
|
+
|
|
16
|
+
See Also
|
|
17
|
+
--------
|
|
18
|
+
plotnine.geom_point : The default `geom` for this `stat`.
|
|
15
19
|
"""
|
|
16
20
|
|
|
17
21
|
DEFAULT_PARAMS = {"geom": "point", "position": "identity", "na_rm": False}
|
|
18
22
|
|
|
19
|
-
|
|
20
|
-
def compute_panel(cls, data, scales, **params):
|
|
23
|
+
def compute_panel(self, data, scales):
|
|
21
24
|
return data.drop_duplicates()
|
plotnine/stats/stat_ydensity.py
CHANGED
|
@@ -69,7 +69,7 @@ class stat_ydensity(stat):
|
|
|
69
69
|
|
|
70
70
|
See Also
|
|
71
71
|
--------
|
|
72
|
-
plotnine.geom_violin
|
|
72
|
+
plotnine.geom_violin : The default `geom` for this `stat`.
|
|
73
73
|
statsmodels.nonparametric.kde.KDEUnivariate
|
|
74
74
|
statsmodels.nonparametric.kde.KDEUnivariate.fit
|
|
75
75
|
"""
|
|
@@ -109,7 +109,7 @@ class stat_ydensity(stat):
|
|
|
109
109
|
return data
|
|
110
110
|
|
|
111
111
|
def setup_params(self, data):
|
|
112
|
-
params = self.params
|
|
112
|
+
params = self.params
|
|
113
113
|
|
|
114
114
|
valid_scale = ("area", "count", "width")
|
|
115
115
|
if params["scale"] not in valid_scale:
|
|
@@ -141,11 +141,9 @@ class stat_ydensity(stat):
|
|
|
141
141
|
for key in missing_params:
|
|
142
142
|
params[key] = stat_density.DEFAULT_PARAMS[key]
|
|
143
143
|
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
def compute_panel(cls, data, scales, **params):
|
|
148
|
-
data = super(cls, cls).compute_panel(data, scales, **params)
|
|
144
|
+
def compute_panel(self, data, scales):
|
|
145
|
+
params = self.params
|
|
146
|
+
data = super().compute_panel(data, scales)
|
|
149
147
|
|
|
150
148
|
if not len(data):
|
|
151
149
|
return data
|
|
@@ -167,20 +165,19 @@ class stat_ydensity(stat):
|
|
|
167
165
|
|
|
168
166
|
return data
|
|
169
167
|
|
|
170
|
-
|
|
171
|
-
def compute_group(cls, data, scales, **params):
|
|
168
|
+
def compute_group(self, data, scales):
|
|
172
169
|
n = len(data)
|
|
173
170
|
if n == 0:
|
|
174
171
|
return pd.DataFrame()
|
|
175
172
|
|
|
176
173
|
weight = data.get("weight")
|
|
177
174
|
|
|
178
|
-
if params["trim"]:
|
|
175
|
+
if self.params["trim"]:
|
|
179
176
|
range_y = data["y"].min(), data["y"].max()
|
|
180
177
|
else:
|
|
181
178
|
range_y = scales.y.dimension()
|
|
182
179
|
|
|
183
|
-
dens = compute_density(data["y"], weight, range_y,
|
|
180
|
+
dens = compute_density(data["y"], weight, range_y, self.params)
|
|
184
181
|
|
|
185
182
|
if not len(dens):
|
|
186
183
|
return dens
|
|
@@ -2,7 +2,7 @@ from .element_blank import element_blank
|
|
|
2
2
|
from .element_line import element_line
|
|
3
3
|
from .element_rect import element_rect
|
|
4
4
|
from .element_text import element_text
|
|
5
|
-
from .margin import margin
|
|
5
|
+
from .margin import margin, margin_auto
|
|
6
6
|
|
|
7
7
|
__all__ = (
|
|
8
8
|
"element_blank",
|
|
@@ -10,4 +10,5 @@ __all__ = (
|
|
|
10
10
|
"element_rect",
|
|
11
11
|
"element_text",
|
|
12
12
|
"margin",
|
|
13
|
+
"margin_auto",
|
|
13
14
|
)
|
|
@@ -5,7 +5,7 @@ from typing import TYPE_CHECKING
|
|
|
5
5
|
from .element_base import element_base
|
|
6
6
|
|
|
7
7
|
if TYPE_CHECKING:
|
|
8
|
-
from typing import Any, Literal,
|
|
8
|
+
from typing import Any, Literal, Sequence
|
|
9
9
|
|
|
10
10
|
|
|
11
11
|
class element_line(element_base):
|
|
@@ -26,6 +26,8 @@ class element_line(element_base):
|
|
|
26
26
|
using tuples, see [](`~matplotlib.lines.line2D.set_linestyle`).
|
|
27
27
|
size : float
|
|
28
28
|
line thickness
|
|
29
|
+
alpha : float
|
|
30
|
+
Opacity value
|
|
29
31
|
kwargs : dict
|
|
30
32
|
Parameters recognised by [](`~matplotlib.lines.line2d`).
|
|
31
33
|
"""
|
|
@@ -33,31 +35,37 @@ class element_line(element_base):
|
|
|
33
35
|
def __init__(
|
|
34
36
|
self,
|
|
35
37
|
*,
|
|
36
|
-
color:
|
|
38
|
+
color: (
|
|
37
39
|
str
|
|
38
40
|
| tuple[float, float, float]
|
|
39
41
|
| tuple[float, float, float, float]
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
42
|
+
| None
|
|
43
|
+
) = None,
|
|
44
|
+
size: float | None = None,
|
|
45
|
+
linetype: str | Sequence[int] | None = None,
|
|
46
|
+
lineend: Literal["butt", "projecting", "round"] | None = None,
|
|
47
|
+
colour: (
|
|
45
48
|
str
|
|
46
49
|
| tuple[float, float, float]
|
|
47
50
|
| tuple[float, float, float, float]
|
|
48
|
-
|
|
51
|
+
| None
|
|
52
|
+
) = None,
|
|
53
|
+
alpha: float | None = None,
|
|
49
54
|
**kwargs: Any,
|
|
50
55
|
):
|
|
51
56
|
super().__init__()
|
|
52
57
|
self.properties.update(**kwargs)
|
|
53
58
|
|
|
54
|
-
color = color if color else colour
|
|
59
|
+
color = color if color is not None else colour
|
|
60
|
+
|
|
55
61
|
if color:
|
|
56
62
|
self.properties["color"] = color
|
|
57
63
|
if size:
|
|
58
64
|
self.properties["linewidth"] = size
|
|
59
65
|
if linetype:
|
|
60
66
|
self.properties["linestyle"] = linetype
|
|
67
|
+
if alpha is not None:
|
|
68
|
+
self.properties["alpha"] = alpha
|
|
61
69
|
|
|
62
70
|
if linetype in ("solid", "-") and lineend:
|
|
63
71
|
self.properties["solid_capstyle"] = lineend
|