plotnine 0.15.0a2__py3-none-any.whl → 0.15.0a3__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/_mpl/layout_manager/_layout_tree.py +16 -6
- plotnine/_utils/__init__.py +4 -2
- plotnine/geoms/annotation_logticks.py +5 -8
- plotnine/geoms/annotation_stripes.py +4 -6
- plotnine/geoms/geom.py +20 -8
- plotnine/geoms/geom_abline.py +3 -2
- plotnine/geoms/geom_blank.py +0 -3
- plotnine/geoms/geom_boxplot.py +4 -4
- plotnine/geoms/geom_crossbar.py +3 -3
- plotnine/geoms/geom_dotplot.py +1 -1
- plotnine/geoms/geom_errorbar.py +2 -2
- plotnine/geoms/geom_errorbarh.py +2 -2
- plotnine/geoms/geom_hline.py +3 -2
- plotnine/geoms/geom_linerange.py +2 -2
- plotnine/geoms/geom_map.py +3 -3
- plotnine/geoms/geom_path.py +10 -11
- plotnine/geoms/geom_point.py +4 -5
- plotnine/geoms/geom_pointrange.py +3 -5
- plotnine/geoms/geom_polygon.py +2 -3
- 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_smooth.py +3 -3
- plotnine/geoms/geom_step.py +2 -2
- plotnine/geoms/geom_text.py +2 -3
- plotnine/geoms/geom_violin.py +4 -5
- plotnine/geoms/geom_vline.py +3 -2
- plotnine/guides/guides.py +1 -1
- plotnine/layer.py +18 -12
- plotnine/mapping/_eval_environment.py +1 -1
- plotnine/scales/scale_color.py +46 -14
- plotnine/scales/scale_continuous.py +5 -4
- plotnine/scales/scale_datetime.py +28 -14
- plotnine/scales/scale_discrete.py +2 -2
- plotnine/scales/scale_xy.py +2 -2
- plotnine/stats/smoothers.py +19 -19
- plotnine/stats/stat.py +15 -25
- plotnine/stats/stat_bin.py +2 -5
- plotnine/stats/stat_bin_2d.py +7 -9
- plotnine/stats/stat_bindot.py +5 -8
- plotnine/stats/stat_boxplot.py +5 -5
- plotnine/stats/stat_count.py +5 -9
- plotnine/stats/stat_density.py +5 -8
- plotnine/stats/stat_density_2d.py +12 -9
- plotnine/stats/stat_ecdf.py +6 -5
- plotnine/stats/stat_ellipse.py +5 -6
- plotnine/stats/stat_function.py +6 -8
- plotnine/stats/stat_hull.py +2 -3
- plotnine/stats/stat_identity.py +1 -2
- plotnine/stats/stat_pointdensity.py +4 -7
- plotnine/stats/stat_qq.py +45 -20
- plotnine/stats/stat_qq_line.py +15 -11
- plotnine/stats/stat_quantile.py +6 -7
- plotnine/stats/stat_sina.py +12 -14
- plotnine/stats/stat_smooth.py +7 -10
- plotnine/stats/stat_sum.py +1 -2
- plotnine/stats/stat_summary.py +6 -9
- plotnine/stats/stat_summary_bin.py +10 -13
- plotnine/stats/stat_unique.py +1 -2
- plotnine/stats/stat_ydensity.py +7 -10
- {plotnine-0.15.0a2.dist-info → plotnine-0.15.0a3.dist-info}/METADATA +3 -3
- {plotnine-0.15.0a2.dist-info → plotnine-0.15.0a3.dist-info}/RECORD +67 -67
- {plotnine-0.15.0a2.dist-info → plotnine-0.15.0a3.dist-info}/WHEEL +1 -1
- {plotnine-0.15.0a2.dist-info → plotnine-0.15.0a3.dist-info}/licenses/LICENSE +0 -0
- {plotnine-0.15.0a2.dist-info → plotnine-0.15.0a3.dist-info}/top_level.txt +0 -0
plotnine/stats/smoothers.py
CHANGED
|
@@ -17,7 +17,7 @@ if TYPE_CHECKING:
|
|
|
17
17
|
from plotnine.mapping import Environment
|
|
18
18
|
|
|
19
19
|
|
|
20
|
-
def predictdf(data, xseq,
|
|
20
|
+
def predictdf(data, xseq, params) -> pd.DataFrame:
|
|
21
21
|
"""
|
|
22
22
|
Make prediction on the data
|
|
23
23
|
|
|
@@ -49,21 +49,21 @@ def predictdf(data, xseq, **params) -> pd.DataFrame:
|
|
|
49
49
|
if not callable(method):
|
|
50
50
|
msg = (
|
|
51
51
|
"'method' should either be a string or a function"
|
|
52
|
-
"with the signature `func(data, xseq,
|
|
52
|
+
"with the signature `func(data, xseq, params)`"
|
|
53
53
|
)
|
|
54
54
|
raise PlotnineError(msg)
|
|
55
55
|
|
|
56
|
-
return method(data, xseq,
|
|
56
|
+
return method(data, xseq, params)
|
|
57
57
|
|
|
58
58
|
|
|
59
|
-
def lm(data, xseq,
|
|
59
|
+
def lm(data, xseq, params) -> pd.DataFrame:
|
|
60
60
|
"""
|
|
61
61
|
Fit OLS / WLS if data has weight
|
|
62
62
|
"""
|
|
63
63
|
import statsmodels.api as sm
|
|
64
64
|
|
|
65
65
|
if params["formula"]:
|
|
66
|
-
return lm_formula(data, xseq,
|
|
66
|
+
return lm_formula(data, xseq, params)
|
|
67
67
|
|
|
68
68
|
X = sm.add_constant(data["x"])
|
|
69
69
|
Xseq = sm.add_constant(xseq)
|
|
@@ -96,7 +96,7 @@ def lm(data, xseq, **params) -> pd.DataFrame:
|
|
|
96
96
|
return data
|
|
97
97
|
|
|
98
98
|
|
|
99
|
-
def lm_formula(data, xseq,
|
|
99
|
+
def lm_formula(data, xseq, params) -> pd.DataFrame:
|
|
100
100
|
"""
|
|
101
101
|
Fit OLS / WLS using a formula
|
|
102
102
|
"""
|
|
@@ -140,14 +140,14 @@ def lm_formula(data, xseq, **params) -> pd.DataFrame:
|
|
|
140
140
|
return data
|
|
141
141
|
|
|
142
142
|
|
|
143
|
-
def rlm(data, xseq,
|
|
143
|
+
def rlm(data, xseq, params) -> pd.DataFrame:
|
|
144
144
|
"""
|
|
145
145
|
Fit RLM
|
|
146
146
|
"""
|
|
147
147
|
import statsmodels.api as sm
|
|
148
148
|
|
|
149
149
|
if params["formula"]:
|
|
150
|
-
return rlm_formula(data, xseq,
|
|
150
|
+
return rlm_formula(data, xseq, params)
|
|
151
151
|
|
|
152
152
|
X = sm.add_constant(data["x"])
|
|
153
153
|
Xseq = sm.add_constant(xseq)
|
|
@@ -170,7 +170,7 @@ def rlm(data, xseq, **params) -> pd.DataFrame:
|
|
|
170
170
|
return data
|
|
171
171
|
|
|
172
172
|
|
|
173
|
-
def rlm_formula(data, xseq,
|
|
173
|
+
def rlm_formula(data, xseq, params) -> pd.DataFrame:
|
|
174
174
|
"""
|
|
175
175
|
Fit RLM using a formula
|
|
176
176
|
"""
|
|
@@ -196,14 +196,14 @@ def rlm_formula(data, xseq, **params) -> pd.DataFrame:
|
|
|
196
196
|
return data
|
|
197
197
|
|
|
198
198
|
|
|
199
|
-
def gls(data, xseq,
|
|
199
|
+
def gls(data, xseq, params) -> pd.DataFrame:
|
|
200
200
|
"""
|
|
201
201
|
Fit GLS
|
|
202
202
|
"""
|
|
203
203
|
import statsmodels.api as sm
|
|
204
204
|
|
|
205
205
|
if params["formula"]:
|
|
206
|
-
return gls_formula(data, xseq,
|
|
206
|
+
return gls_formula(data, xseq, params)
|
|
207
207
|
|
|
208
208
|
X = sm.add_constant(data["x"])
|
|
209
209
|
Xseq = sm.add_constant(xseq)
|
|
@@ -227,7 +227,7 @@ def gls(data, xseq, **params) -> pd.DataFrame:
|
|
|
227
227
|
return data
|
|
228
228
|
|
|
229
229
|
|
|
230
|
-
def gls_formula(data, xseq,
|
|
230
|
+
def gls_formula(data, xseq, params):
|
|
231
231
|
"""
|
|
232
232
|
Fit GLL using a formula
|
|
233
233
|
"""
|
|
@@ -258,14 +258,14 @@ def gls_formula(data, xseq, **params):
|
|
|
258
258
|
return data
|
|
259
259
|
|
|
260
260
|
|
|
261
|
-
def glm(data, xseq,
|
|
261
|
+
def glm(data, xseq, params) -> pd.DataFrame:
|
|
262
262
|
"""
|
|
263
263
|
Fit GLM
|
|
264
264
|
"""
|
|
265
265
|
import statsmodels.api as sm
|
|
266
266
|
|
|
267
267
|
if params["formula"]:
|
|
268
|
-
return glm_formula(data, xseq,
|
|
268
|
+
return glm_formula(data, xseq, params)
|
|
269
269
|
|
|
270
270
|
X = sm.add_constant(data["x"])
|
|
271
271
|
Xseq = sm.add_constant(xseq)
|
|
@@ -292,7 +292,7 @@ def glm(data, xseq, **params) -> pd.DataFrame:
|
|
|
292
292
|
return data
|
|
293
293
|
|
|
294
294
|
|
|
295
|
-
def glm_formula(data, xseq,
|
|
295
|
+
def glm_formula(data, xseq, params):
|
|
296
296
|
"""
|
|
297
297
|
Fit with GLM formula
|
|
298
298
|
"""
|
|
@@ -321,7 +321,7 @@ def glm_formula(data, xseq, **params):
|
|
|
321
321
|
return data
|
|
322
322
|
|
|
323
323
|
|
|
324
|
-
def lowess(data, xseq,
|
|
324
|
+
def lowess(data, xseq, params) -> pd.DataFrame:
|
|
325
325
|
"""
|
|
326
326
|
Lowess fitting
|
|
327
327
|
"""
|
|
@@ -351,7 +351,7 @@ def lowess(data, xseq, **params) -> pd.DataFrame:
|
|
|
351
351
|
return data
|
|
352
352
|
|
|
353
353
|
|
|
354
|
-
def loess(data, xseq,
|
|
354
|
+
def loess(data, xseq, params) -> pd.DataFrame:
|
|
355
355
|
"""
|
|
356
356
|
Loess smoothing
|
|
357
357
|
"""
|
|
@@ -402,7 +402,7 @@ def loess(data, xseq, **params) -> pd.DataFrame:
|
|
|
402
402
|
return data
|
|
403
403
|
|
|
404
404
|
|
|
405
|
-
def mavg(data, xseq,
|
|
405
|
+
def mavg(data, xseq, params) -> pd.DataFrame:
|
|
406
406
|
"""
|
|
407
407
|
Fit moving average
|
|
408
408
|
"""
|
|
@@ -426,7 +426,7 @@ def mavg(data, xseq, **params) -> pd.DataFrame:
|
|
|
426
426
|
return data
|
|
427
427
|
|
|
428
428
|
|
|
429
|
-
def gpr(data, xseq,
|
|
429
|
+
def gpr(data, xseq, params):
|
|
430
430
|
"""
|
|
431
431
|
Fit gaussian process
|
|
432
432
|
"""
|
plotnine/stats/stat.py
CHANGED
|
@@ -195,9 +195,9 @@ class stat(ABC, metaclass=Register):
|
|
|
195
195
|
|
|
196
196
|
return data
|
|
197
197
|
|
|
198
|
-
def setup_params(self, data: pd.DataFrame)
|
|
198
|
+
def setup_params(self, data: pd.DataFrame):
|
|
199
199
|
"""
|
|
200
|
-
Override this to verify or adjust parameters
|
|
200
|
+
Override this to verify and/or adjust parameters
|
|
201
201
|
|
|
202
202
|
Parameters
|
|
203
203
|
----------
|
|
@@ -209,7 +209,6 @@ class stat(ABC, metaclass=Register):
|
|
|
209
209
|
out :
|
|
210
210
|
Parameters used by the stats.
|
|
211
211
|
"""
|
|
212
|
-
return self.params
|
|
213
212
|
|
|
214
213
|
def setup_data(self, data: pd.DataFrame) -> pd.DataFrame:
|
|
215
214
|
"""
|
|
@@ -227,9 +226,7 @@ class stat(ABC, metaclass=Register):
|
|
|
227
226
|
"""
|
|
228
227
|
return data
|
|
229
228
|
|
|
230
|
-
def finish_layer(
|
|
231
|
-
self, data: pd.DataFrame, params: dict[str, Any]
|
|
232
|
-
) -> pd.DataFrame:
|
|
229
|
+
def finish_layer(self, data: pd.DataFrame) -> pd.DataFrame:
|
|
233
230
|
"""
|
|
234
231
|
Modify data after the aesthetics have been mapped
|
|
235
232
|
|
|
@@ -257,9 +254,8 @@ class stat(ABC, metaclass=Register):
|
|
|
257
254
|
"""
|
|
258
255
|
return data
|
|
259
256
|
|
|
260
|
-
@classmethod
|
|
261
257
|
def compute_layer(
|
|
262
|
-
|
|
258
|
+
self, data: pd.DataFrame, layout: Layout
|
|
263
259
|
) -> pd.DataFrame:
|
|
264
260
|
"""
|
|
265
261
|
Calculate statistics for this layers
|
|
@@ -275,22 +271,20 @@ class stat(ABC, metaclass=Register):
|
|
|
275
271
|
----------
|
|
276
272
|
data :
|
|
277
273
|
Data points for all objects in a layer.
|
|
278
|
-
params :
|
|
279
|
-
Stat parameters
|
|
280
274
|
layout :
|
|
281
275
|
Panel layout information
|
|
282
276
|
"""
|
|
283
277
|
check_required_aesthetics(
|
|
284
|
-
|
|
285
|
-
list(data.columns) + list(params.keys()),
|
|
286
|
-
|
|
278
|
+
self.REQUIRED_AES,
|
|
279
|
+
list(data.columns) + list(self.params.keys()),
|
|
280
|
+
self.__class__.__name__,
|
|
287
281
|
)
|
|
288
282
|
|
|
289
283
|
data = remove_missing(
|
|
290
284
|
data,
|
|
291
|
-
na_rm=params.get("na_rm", False),
|
|
292
|
-
vars=list(
|
|
293
|
-
name=
|
|
285
|
+
na_rm=self.params.get("na_rm", False),
|
|
286
|
+
vars=list(self.REQUIRED_AES | self.NON_MISSING_AES),
|
|
287
|
+
name=self.__class__.__name__,
|
|
294
288
|
finite=True,
|
|
295
289
|
)
|
|
296
290
|
|
|
@@ -304,14 +298,11 @@ class stat(ABC, metaclass=Register):
|
|
|
304
298
|
if len(pdata) == 0:
|
|
305
299
|
return pdata
|
|
306
300
|
pscales = layout.get_scales(pdata["PANEL"].iloc[0])
|
|
307
|
-
return
|
|
301
|
+
return self.compute_panel(pdata, pscales)
|
|
308
302
|
|
|
309
303
|
return groupby_apply(data, "PANEL", fn)
|
|
310
304
|
|
|
311
|
-
|
|
312
|
-
def compute_panel(
|
|
313
|
-
cls, data: pd.DataFrame, scales: pos_scales, **params: Any
|
|
314
|
-
):
|
|
305
|
+
def compute_panel(self, data: pd.DataFrame, scales: pos_scales):
|
|
315
306
|
"""
|
|
316
307
|
Calculate the statistics for all the groups
|
|
317
308
|
|
|
@@ -341,7 +332,7 @@ class stat(ABC, metaclass=Register):
|
|
|
341
332
|
|
|
342
333
|
stats = []
|
|
343
334
|
for _, old in data.groupby("group"):
|
|
344
|
-
new =
|
|
335
|
+
new = self.compute_group(old, scales)
|
|
345
336
|
new.reset_index(drop=True, inplace=True)
|
|
346
337
|
unique = uniquecols(old)
|
|
347
338
|
missing = unique.columns.difference(new.columns)
|
|
@@ -365,9 +356,8 @@ class stat(ABC, metaclass=Register):
|
|
|
365
356
|
# it completely.
|
|
366
357
|
return stats
|
|
367
358
|
|
|
368
|
-
@classmethod
|
|
369
359
|
def compute_group(
|
|
370
|
-
|
|
360
|
+
self, data: pd.DataFrame, scales: pos_scales
|
|
371
361
|
) -> pd.DataFrame:
|
|
372
362
|
"""
|
|
373
363
|
Calculate statistics for the group
|
|
@@ -390,7 +380,7 @@ class stat(ABC, metaclass=Register):
|
|
|
390
380
|
Parameters
|
|
391
381
|
"""
|
|
392
382
|
msg = "{} should implement this method."
|
|
393
|
-
raise NotImplementedError(msg.format(
|
|
383
|
+
raise NotImplementedError(msg.format(self.__class__.__name__))
|
|
394
384
|
|
|
395
385
|
def __radd__(self, other: ggplot) -> ggplot:
|
|
396
386
|
"""
|
plotnine/stats/stat_bin.py
CHANGED
|
@@ -100,7 +100,6 @@ class stat_bin(stat):
|
|
|
100
100
|
and params["binwidth"] is None
|
|
101
101
|
and params["bins"] is None
|
|
102
102
|
):
|
|
103
|
-
params = params.copy()
|
|
104
103
|
params["bins"] = freedman_diaconis_bins(data["x"])
|
|
105
104
|
msg = (
|
|
106
105
|
"'stat_bin()' using 'bins = {}'. "
|
|
@@ -108,10 +107,8 @@ class stat_bin(stat):
|
|
|
108
107
|
)
|
|
109
108
|
warn(msg.format(params["bins"]), PlotnineWarning)
|
|
110
109
|
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
@classmethod
|
|
114
|
-
def compute_group(cls, data, scales, **params):
|
|
110
|
+
def compute_group(self, data, scales):
|
|
111
|
+
params = self.params
|
|
115
112
|
if params["breaks"] is not None:
|
|
116
113
|
breaks = np.asarray(params["breaks"])
|
|
117
114
|
if hasattr(scales.x, "transform"):
|
plotnine/stats/stat_bin_2d.py
CHANGED
|
@@ -66,18 +66,16 @@ class stat_bin_2d(stat):
|
|
|
66
66
|
CREATES = {"xmin", "xmax", "ymin", "ymax", "count", "density"}
|
|
67
67
|
|
|
68
68
|
def setup_params(self, data):
|
|
69
|
-
params = self.params
|
|
69
|
+
params = self.params
|
|
70
70
|
params["bins"] = dual_param(params["bins"])
|
|
71
71
|
params["breaks"] = dual_param(params["breaks"])
|
|
72
72
|
params["binwidth"] = dual_param(params["binwidth"])
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
binwidth = params["binwidth"]
|
|
80
|
-
drop = params["drop"]
|
|
73
|
+
|
|
74
|
+
def compute_group(self, data, scales):
|
|
75
|
+
bins = self.params["bins"]
|
|
76
|
+
breaks = self.params["breaks"]
|
|
77
|
+
binwidth = self.params["binwidth"]
|
|
78
|
+
drop = self.params["drop"]
|
|
81
79
|
weight = data.get("weight")
|
|
82
80
|
|
|
83
81
|
if weight is None:
|
plotnine/stats/stat_bindot.py
CHANGED
|
@@ -113,7 +113,6 @@ class stat_bindot(stat):
|
|
|
113
113
|
and params["binwidth"] is None
|
|
114
114
|
and params["bins"] is None
|
|
115
115
|
):
|
|
116
|
-
params = params.copy()
|
|
117
116
|
params["bins"] = freedman_diaconis_bins(data["x"])
|
|
118
117
|
msg = (
|
|
119
118
|
"'stat_bin()' using 'bins = {}'. "
|
|
@@ -121,10 +120,8 @@ class stat_bindot(stat):
|
|
|
121
120
|
)
|
|
122
121
|
warn(msg.format(params["bins"]), PlotnineWarning)
|
|
123
122
|
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
@classmethod
|
|
127
|
-
def compute_panel(cls, data, scales, **params):
|
|
123
|
+
def compute_panel(self, data, scales):
|
|
124
|
+
params = self.params
|
|
128
125
|
if (
|
|
129
126
|
params["method"] == "dotdensity"
|
|
130
127
|
and params["binpositions"] == "all"
|
|
@@ -160,10 +157,10 @@ class stat_bindot(stat):
|
|
|
160
157
|
data["binwidth"] = newdata["binwidth"]
|
|
161
158
|
data["weight"] = newdata["weight"]
|
|
162
159
|
data["bincenter"] = newdata["bincenter"]
|
|
163
|
-
return super(
|
|
160
|
+
return super().compute_panel(data, scales)
|
|
164
161
|
|
|
165
|
-
|
|
166
|
-
|
|
162
|
+
def compute_group(self, data, scales):
|
|
163
|
+
params = self.params
|
|
167
164
|
# Check that weights are whole numbers
|
|
168
165
|
# (for dots, weights must be whole)
|
|
169
166
|
weight = data.get("weight")
|
plotnine/stats/stat_boxplot.py
CHANGED
|
@@ -91,10 +91,8 @@ class stat_boxplot(stat):
|
|
|
91
91
|
if self.params["width"] is None:
|
|
92
92
|
x = data.get("x", 0)
|
|
93
93
|
self.params["width"] = resolution(x, False) * 0.75
|
|
94
|
-
return self.params
|
|
95
94
|
|
|
96
|
-
|
|
97
|
-
def compute_group(cls, data, scales, **params):
|
|
95
|
+
def compute_group(self, data, scales):
|
|
98
96
|
n = len(data)
|
|
99
97
|
y = data["y"].to_numpy()
|
|
100
98
|
if "weight" in data:
|
|
@@ -103,12 +101,14 @@ class stat_boxplot(stat):
|
|
|
103
101
|
else:
|
|
104
102
|
weights = None
|
|
105
103
|
total_weight = len(y)
|
|
106
|
-
res = weighted_boxplot_stats(
|
|
104
|
+
res = weighted_boxplot_stats(
|
|
105
|
+
y, weights=weights, whis=self.params["coef"]
|
|
106
|
+
)
|
|
107
107
|
|
|
108
108
|
if len(np.unique(data["x"])) > 1:
|
|
109
109
|
width = np.ptp(data["x"]) * 0.9
|
|
110
110
|
else:
|
|
111
|
-
width = params["width"]
|
|
111
|
+
width = self.params["width"]
|
|
112
112
|
|
|
113
113
|
if isinstance(data["x"].dtype, pd.CategoricalDtype):
|
|
114
114
|
x = data["x"].iloc[0]
|
plotnine/stats/stat_count.py
CHANGED
|
@@ -49,21 +49,17 @@ class stat_count(stat):
|
|
|
49
49
|
CREATES = {"count", "prop"}
|
|
50
50
|
|
|
51
51
|
def setup_params(self, data):
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
params["width"] = resolution(data["x"], False) * 0.9
|
|
52
|
+
if self.params["width"] is None:
|
|
53
|
+
self.params["width"] = resolution(data["x"], False) * 0.9
|
|
55
54
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
@classmethod
|
|
59
|
-
def compute_group(cls, data, scales, **params):
|
|
55
|
+
def compute_group(self, data, scales):
|
|
60
56
|
x = data["x"]
|
|
61
|
-
if ("y" in data) or ("y" in params):
|
|
57
|
+
if ("y" in data) or ("y" in self.params):
|
|
62
58
|
msg = "stat_count() must not be used with a y aesthetic"
|
|
63
59
|
raise PlotnineError(msg)
|
|
64
60
|
|
|
65
61
|
weight = data.get("weight", [1] * len(x))
|
|
66
|
-
width = params["width"]
|
|
62
|
+
width = self.params["width"]
|
|
67
63
|
xdata_long = pd.DataFrame({"x": x, "weight": weight})
|
|
68
64
|
# weighted frequency count
|
|
69
65
|
count = xdata_long.pivot_table("weight", index=["x"], aggfunc="sum")[
|
plotnine/stats/stat_density.py
CHANGED
|
@@ -126,7 +126,7 @@ class stat_density(stat):
|
|
|
126
126
|
CREATES = {"density", "count", "scaled", "n"}
|
|
127
127
|
|
|
128
128
|
def setup_params(self, data):
|
|
129
|
-
params = self.params
|
|
129
|
+
params = self.params
|
|
130
130
|
lookup = {
|
|
131
131
|
"biweight": "biw",
|
|
132
132
|
"cosine": "cos",
|
|
@@ -148,21 +148,18 @@ class stat_density(stat):
|
|
|
148
148
|
)
|
|
149
149
|
raise PlotnineError(msg)
|
|
150
150
|
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
@classmethod
|
|
154
|
-
def compute_group(cls, data, scales, **params):
|
|
151
|
+
def compute_group(self, data, scales):
|
|
155
152
|
weight = data.get("weight")
|
|
156
153
|
|
|
157
|
-
if params["trim"]:
|
|
154
|
+
if self.params["trim"]:
|
|
158
155
|
range_x = data["x"].min(), data["x"].max()
|
|
159
156
|
else:
|
|
160
157
|
range_x = scales.x.dimension()
|
|
161
158
|
|
|
162
|
-
return compute_density(data["x"], weight, range_x,
|
|
159
|
+
return compute_density(data["x"], weight, range_x, self.params)
|
|
163
160
|
|
|
164
161
|
|
|
165
|
-
def compute_density(x, weight, range,
|
|
162
|
+
def compute_density(x, weight, range, params):
|
|
166
163
|
"""
|
|
167
164
|
Compute density
|
|
168
165
|
"""
|
|
@@ -1,12 +1,17 @@
|
|
|
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
|
|
|
4
|
-
from ..doctools import document
|
|
5
8
|
from .density import get_var_type, kde
|
|
6
9
|
from .stat import stat
|
|
7
10
|
|
|
11
|
+
if TYPE_CHECKING:
|
|
12
|
+
from plotnine.typing import FloatArrayLike
|
|
13
|
+
|
|
8
14
|
|
|
9
|
-
@document
|
|
10
15
|
class stat_density_2d(stat):
|
|
11
16
|
"""
|
|
12
17
|
Compute 2D kernel density estimation
|
|
@@ -66,7 +71,7 @@ class stat_density_2d(stat):
|
|
|
66
71
|
CREATES = {"y"}
|
|
67
72
|
|
|
68
73
|
def setup_params(self, data):
|
|
69
|
-
params = self.params
|
|
74
|
+
params = self.params
|
|
70
75
|
if params["kde_params"] is None:
|
|
71
76
|
params["kde_params"] = {}
|
|
72
77
|
|
|
@@ -78,10 +83,8 @@ class stat_density_2d(stat):
|
|
|
78
83
|
y_type = get_var_type(data["y"])
|
|
79
84
|
kde_params["var_type"] = f"{x_type}{y_type}"
|
|
80
85
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
@classmethod
|
|
84
|
-
def compute_group(cls, data, scales, **params):
|
|
86
|
+
def compute_group(self, data, scales):
|
|
87
|
+
params = self.params
|
|
85
88
|
package = params["package"]
|
|
86
89
|
kde_params = params["kde_params"]
|
|
87
90
|
|
|
@@ -118,7 +121,7 @@ class stat_density_2d(stat):
|
|
|
118
121
|
return data
|
|
119
122
|
|
|
120
123
|
|
|
121
|
-
def contour_lines(X, Y, Z, levels):
|
|
124
|
+
def contour_lines(X, Y, Z, levels: int | FloatArrayLike):
|
|
122
125
|
"""
|
|
123
126
|
Calculate contour lines
|
|
124
127
|
"""
|
|
@@ -152,7 +155,7 @@ def contour_lines(X, Y, Z, levels):
|
|
|
152
155
|
level_values = []
|
|
153
156
|
start_pid = 1
|
|
154
157
|
for level in levels:
|
|
155
|
-
vertices, *_ = cgen.create_contour(level)
|
|
158
|
+
vertices, *_ = cgen.create_contour(level) # pyright: ignore[reportArgumentType]
|
|
156
159
|
for pid, piece in enumerate(vertices, start=start_pid):
|
|
157
160
|
n = len(piece) # pyright: ignore
|
|
158
161
|
segments.append(piece)
|
plotnine/stats/stat_ecdf.py
CHANGED
|
@@ -50,17 +50,18 @@ class stat_ecdf(stat):
|
|
|
50
50
|
DEFAULT_AES = {"y": after_stat("ecdf")}
|
|
51
51
|
CREATES = {"ecdf"}
|
|
52
52
|
|
|
53
|
-
|
|
54
|
-
def compute_group(cls, data, scales, **params):
|
|
53
|
+
def compute_group(self, data, scales):
|
|
55
54
|
from statsmodels.distributions.empirical_distribution import ECDF
|
|
56
55
|
|
|
56
|
+
n, pad = self.params["n"], self.params["pad"]
|
|
57
|
+
|
|
57
58
|
# If n is None, use raw values; otherwise interpolate
|
|
58
|
-
if
|
|
59
|
+
if n is None:
|
|
59
60
|
x = np.unique(data["x"])
|
|
60
61
|
else:
|
|
61
|
-
x = np.linspace(data["x"].min(), data["x"].max(),
|
|
62
|
+
x = np.linspace(data["x"].min(), data["x"].max(), n)
|
|
62
63
|
|
|
63
|
-
if
|
|
64
|
+
if pad:
|
|
64
65
|
x = np.hstack([-np.inf, x, np.inf])
|
|
65
66
|
|
|
66
67
|
ecdf = ECDF(data["x"].to_numpy())(x)
|
plotnine/stats/stat_ellipse.py
CHANGED
|
@@ -49,14 +49,13 @@ class stat_ellipse(stat):
|
|
|
49
49
|
"segments": 51,
|
|
50
50
|
}
|
|
51
51
|
|
|
52
|
-
|
|
53
|
-
def compute_group(cls, data, scales, **params):
|
|
52
|
+
def compute_group(self, data, scales):
|
|
54
53
|
import scipy.stats as stats
|
|
55
54
|
from scipy import linalg
|
|
56
55
|
|
|
57
|
-
level = params["level"]
|
|
58
|
-
segments = params["segments"]
|
|
59
|
-
type_ = params["type"]
|
|
56
|
+
level = self.params["level"]
|
|
57
|
+
segments = self.params["segments"]
|
|
58
|
+
type_ = self.params["type"]
|
|
60
59
|
|
|
61
60
|
dfn = 2
|
|
62
61
|
dfd = len(data) - 1
|
|
@@ -203,7 +202,7 @@ def cov_trob(
|
|
|
203
202
|
wt = wt[wt > 0]
|
|
204
203
|
n, _ = x.shape
|
|
205
204
|
|
|
206
|
-
wt = wt[:, np.newaxis]
|
|
205
|
+
wt = wt[:, np.newaxis] # pyright: ignore[reportCallIssue,reportArgumentType,reportOptionalSubscript]
|
|
207
206
|
|
|
208
207
|
# loc
|
|
209
208
|
use_loc = False
|
plotnine/stats/stat_function.py
CHANGED
|
@@ -82,14 +82,12 @@ class stat_function(stat):
|
|
|
82
82
|
"stat_function requires parameter 'fun' to be "
|
|
83
83
|
"a function or any other callable object"
|
|
84
84
|
)
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
args = params["args"]
|
|
92
|
-
xlim = params["xlim"]
|
|
85
|
+
|
|
86
|
+
def compute_group(self, data, scales):
|
|
87
|
+
old_fun: Callable[..., FloatArrayLike] = self.params["fun"]
|
|
88
|
+
n = self.params["n"]
|
|
89
|
+
args = self.params["args"]
|
|
90
|
+
xlim = self.params["xlim"]
|
|
93
91
|
range_x = xlim or scales.x.dimension((0, 0))
|
|
94
92
|
|
|
95
93
|
if isinstance(args, (list, tuple)):
|
plotnine/stats/stat_hull.py
CHANGED
|
@@ -47,12 +47,11 @@ class stat_hull(stat):
|
|
|
47
47
|
}
|
|
48
48
|
CREATES = {"area"}
|
|
49
49
|
|
|
50
|
-
|
|
51
|
-
def compute_group(cls, data, scales, **params):
|
|
50
|
+
def compute_group(self, data, scales):
|
|
52
51
|
from scipy.spatial import ConvexHull
|
|
53
52
|
|
|
54
53
|
hull = ConvexHull(
|
|
55
|
-
data[["x", "y"]], qhull_options=params["qhull_options"]
|
|
54
|
+
data[["x", "y"]], qhull_options=self.params["qhull_options"]
|
|
56
55
|
)
|
|
57
56
|
idx = np.hstack([hull.vertices, hull.vertices[0]])
|
|
58
57
|
|
plotnine/stats/stat_identity.py
CHANGED
|
@@ -51,7 +51,7 @@ class stat_pointdensity(stat):
|
|
|
51
51
|
CREATES = {"density"}
|
|
52
52
|
|
|
53
53
|
def setup_params(self, data):
|
|
54
|
-
params = self.params
|
|
54
|
+
params = self.params
|
|
55
55
|
if params["kde_params"] is None:
|
|
56
56
|
params["kde_params"] = {}
|
|
57
57
|
|
|
@@ -63,12 +63,9 @@ class stat_pointdensity(stat):
|
|
|
63
63
|
y_type = get_var_type(data["y"])
|
|
64
64
|
kde_params["var_type"] = f"{x_type}{y_type}"
|
|
65
65
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
def compute_group(cls, data, scales, **params):
|
|
70
|
-
package = params["package"]
|
|
71
|
-
kde_params = params["kde_params"]
|
|
66
|
+
def compute_group(self, data, scales):
|
|
67
|
+
package = self.params["package"]
|
|
68
|
+
kde_params = self.params["kde_params"]
|
|
72
69
|
|
|
73
70
|
var_data = np.array([data["x"].to_numpy(), data["y"].to_numpy()]).T
|
|
74
71
|
density = kde(var_data, var_data, package, **kde_params)
|