iqplot 0.3.7__tar.gz → 0.3.8__tar.gz
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.
- {iqplot-0.3.7 → iqplot-0.3.8}/.gitignore +3 -0
- iqplot-0.3.8/PKG-INFO +41 -0
- {iqplot-0.3.7 → iqplot-0.3.8}/iqplot/__init__.py +2 -2
- {iqplot-0.3.7 → iqplot-0.3.8}/iqplot/cat.py +125 -95
- {iqplot-0.3.7 → iqplot-0.3.8}/iqplot/dist.py +350 -192
- {iqplot-0.3.7 → iqplot-0.3.8}/iqplot/utils.py +76 -43
- iqplot-0.3.8/pyproject.toml +122 -0
- iqplot-0.3.8/test/test_plots.ipynb +2098 -0
- iqplot-0.3.7/PKG-INFO +0 -20
- iqplot-0.3.7/doc/.gitignore +0 -2
- iqplot-0.3.7/doc/Makefile +0 -20
- iqplot-0.3.7/doc/_static/custom.css +0 -44
- iqplot-0.3.7/doc/_static/logo.png +0 -0
- iqplot-0.3.7/doc/_templates/breadcrumbs.html +0 -42
- iqplot-0.3.7/doc/_templates/footer.html +0 -11
- iqplot-0.3.7/doc/_templates/layout.html +0 -8
- iqplot-0.3.7/doc/conf.py +0 -173
- iqplot-0.3.7/doc/credits_and_citation.rst +0 -28
- iqplot-0.3.7/doc/getting_started/installation.rst +0 -30
- iqplot-0.3.7/doc/getting_started/purpose.rst +0 -35
- iqplot-0.3.7/doc/index.rst +0 -29
- iqplot-0.3.7/doc/make.bat +0 -35
- iqplot-0.3.7/doc/user_guide/.gitignore +0 -2
- iqplot-0.3.7/doc/user_guide/api.rst +0 -18
- iqplot-0.3.7/doc/user_guide/holoviews.ipynb +0 -2988
- iqplot-0.3.7/doc/user_guide/omissions.ipynb +0 -1853
- iqplot-0.3.7/doc/user_guide/user_guide.ipynb +0 -2395
- iqplot-0.3.7/iqplot/.gitignore +0 -2
- iqplot-0.3.7/iqplot.egg-info/PKG-INFO +0 -20
- iqplot-0.3.7/iqplot.egg-info/SOURCES.txt +0 -34
- iqplot-0.3.7/iqplot.egg-info/dependency_links.txt +0 -1
- iqplot-0.3.7/iqplot.egg-info/requires.txt +0 -5
- iqplot-0.3.7/iqplot.egg-info/top_level.txt +0 -1
- iqplot-0.3.7/requirements.txt +0 -5
- iqplot-0.3.7/setup.cfg +0 -10
- iqplot-0.3.7/setup.py +0 -36
- {iqplot-0.3.7 → iqplot-0.3.8}/LICENSE +0 -0
- {iqplot-0.3.7 → iqplot-0.3.8}/README.md +0 -0
iqplot-0.3.8/PKG-INFO
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: iqplot
|
|
3
|
+
Version: 0.3.8
|
|
4
|
+
Summary: Generate Bokeh plots for data sets with one quantitative variable.
|
|
5
|
+
Project-URL: Homepage, https://github.com/justinbois/iqplot
|
|
6
|
+
Project-URL: Documentation, http://iqplot.github.io/
|
|
7
|
+
Project-URL: Repository, https://github.com/justinbois/iqplot
|
|
8
|
+
Project-URL: Issues, https://github.com/justinbois/iqplot/issues
|
|
9
|
+
Author-email: Justin Bois <bois@caltech.edu>
|
|
10
|
+
Maintainer-email: Justin Bois <bois@caltech.edu>
|
|
11
|
+
License-Expression: MIT
|
|
12
|
+
License-File: LICENSE
|
|
13
|
+
Keywords: bokeh,box plot,ecdf,histogram,plotting,visualization
|
|
14
|
+
Classifier: Development Status :: 4 - Beta
|
|
15
|
+
Classifier: Intended Audience :: Developers
|
|
16
|
+
Classifier: Intended Audience :: Science/Research
|
|
17
|
+
Classifier: Programming Language :: Python :: 3
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
22
|
+
Classifier: Topic :: Scientific/Engineering :: Visualization
|
|
23
|
+
Requires-Python: >=3.10
|
|
24
|
+
Requires-Dist: bokeh>=3.0
|
|
25
|
+
Requires-Dist: colorcet
|
|
26
|
+
Requires-Dist: numpy
|
|
27
|
+
Requires-Dist: pandas
|
|
28
|
+
Provides-Extra: data
|
|
29
|
+
Requires-Dist: polars; extra == 'data'
|
|
30
|
+
Requires-Dist: xarray; extra == 'data'
|
|
31
|
+
Provides-Extra: speedups
|
|
32
|
+
Requires-Dist: numba; extra == 'speedups'
|
|
33
|
+
Description-Content-Type: text/markdown
|
|
34
|
+
|
|
35
|
+
# iqplot
|
|
36
|
+
|
|
37
|
+
[](https://doi.org/10.22002/D1.20286)
|
|
38
|
+
|
|
39
|
+
A utility to use Bokeh to generate plots for data sets containing one quantitative variable and an arbitrary many categorical variables. It generates strip plots, box plots, histograms, and ECDFs.
|
|
40
|
+
|
|
41
|
+
Read the [documentation](http://iqplot.github.io/) for details.
|
|
@@ -96,16 +96,15 @@ def strip(
|
|
|
96
96
|
tooltips : list of 2-tuples
|
|
97
97
|
Specification for tooltips as per Bokeh specifications. For
|
|
98
98
|
example, if we want `col1` and `col2` tooltips, we can use
|
|
99
|
-
`tooltips=[('label 1'
|
|
99
|
+
`tooltips=[('label 1', '@col1'), ('label 2', '@col2')]`.
|
|
100
100
|
marker : str, default 'circle'
|
|
101
|
-
Name of marker to be used in the plot
|
|
102
|
-
|
|
103
|
-
'
|
|
104
|
-
'
|
|
105
|
-
'triangle', 'x']
|
|
101
|
+
Name of marker to be used in the plot. Must be one of
|
|
102
|
+
['asterisk', 'circle', 'circle_cross', 'circle_x', 'cross',
|
|
103
|
+
'dash', 'diamond', 'diamond_cross', 'hex', 'inverted_triangle',
|
|
104
|
+
'square', 'square_cross', 'square_x', 'triangle', 'x'].
|
|
106
105
|
spread : str or None, default None
|
|
107
106
|
If 'jitter', spread points out using a jitter transform. If
|
|
108
|
-
'swarm', spread points in beeswarm style.
|
|
107
|
+
'swarm', spread points in beeswarm style. If None or 'none', do
|
|
109
108
|
not spread.
|
|
110
109
|
cat_grid : bool, default False
|
|
111
110
|
If True, show grid lines for categorical axis.
|
|
@@ -125,9 +124,9 @@ def strip(
|
|
|
125
124
|
|
|
126
125
|
- 'corral': Either 'gutter' (default) or 'wrap'. This
|
|
127
126
|
specifies how points that are moved too far out are dealt
|
|
128
|
-
with. Using 'gutter', points are
|
|
127
|
+
with. Using 'gutter', points are overlaid at the maximum
|
|
129
128
|
allowed distance. Using 'wrap', points are reflected inwards
|
|
130
|
-
|
|
129
|
+
from the maximal extent and possibly overlaid with other
|
|
131
130
|
points.
|
|
132
131
|
|
|
133
132
|
- 'priority': Either 'ascending' (default) or 'descending'.
|
|
@@ -138,7 +137,8 @@ def strip(
|
|
|
138
137
|
default 0.
|
|
139
138
|
parcoord_kwargs : dict
|
|
140
139
|
Keyword arguments to be passed to `p.line()` when making lines
|
|
141
|
-
for
|
|
140
|
+
for the parallel coordinate plot. Default is to have one-pixel
|
|
141
|
+
gray lines.
|
|
142
142
|
jitter : bool, default False
|
|
143
143
|
Deprecated, use `spread`.
|
|
144
144
|
horizontal : bool or None, default None
|
|
@@ -188,12 +188,12 @@ def strip(
|
|
|
188
188
|
# Check spread
|
|
189
189
|
if spread is not None:
|
|
190
190
|
spread = spread.lower()
|
|
191
|
-
if spread ==
|
|
191
|
+
if spread == "beeswarm":
|
|
192
192
|
raise RuntimeError("Did you mean `spread='swarm'`?")
|
|
193
|
-
if spread not in (
|
|
193
|
+
if spread not in ("swarm", "jitter", "none", None):
|
|
194
194
|
raise RuntimeError(
|
|
195
195
|
"Invalid `spread`. Valid choices are 'swarm', 'jitter', and None."
|
|
196
|
-
|
|
196
|
+
)
|
|
197
197
|
|
|
198
198
|
if spread is not None and spread != "none" and parcoord_column is not None:
|
|
199
199
|
raise NotImplementedError(
|
|
@@ -209,6 +209,10 @@ def strip(
|
|
|
209
209
|
else:
|
|
210
210
|
show_legend = not _color_column_hexcodes(data, color_column)
|
|
211
211
|
|
|
212
|
+
# The legend for a strip plot comes from `color_column`, not `cats`,
|
|
213
|
+
# so only `order` is checked here.
|
|
214
|
+
utils._check_cats_none(cats, order)
|
|
215
|
+
|
|
212
216
|
data, q, cats, show_legend = utils._data_cats(data, q, cats, show_legend, None)
|
|
213
217
|
order = utils._order_to_str(order)
|
|
214
218
|
|
|
@@ -223,9 +227,9 @@ def strip(
|
|
|
223
227
|
data, grouped, q, order, color_column, q_axis, kwargs
|
|
224
228
|
)
|
|
225
229
|
else:
|
|
226
|
-
if
|
|
230
|
+
if isinstance(p.x_range, bokeh.models.ranges.FactorRange) and q_axis == "x":
|
|
227
231
|
raise RuntimeError("`q_axis` is 'x', but `p` has a categorical x-axis.")
|
|
228
|
-
elif
|
|
232
|
+
elif isinstance(p.y_range, bokeh.models.ranges.FactorRange) and q_axis == "y":
|
|
229
233
|
raise RuntimeError("`q_axis` is 'y', but `p` has a categorical y-axis.")
|
|
230
234
|
|
|
231
235
|
_, factors, color_factors = _get_cat_range(
|
|
@@ -237,7 +241,7 @@ def strip(
|
|
|
237
241
|
|
|
238
242
|
if jitter_kwargs is None:
|
|
239
243
|
jitter_kwargs = dict(width=0.1, mean=0, distribution="normal")
|
|
240
|
-
elif
|
|
244
|
+
elif not isinstance(jitter_kwargs, dict):
|
|
241
245
|
raise RuntimeError("`jitter_kwargs` must be a dict.")
|
|
242
246
|
elif "width" not in jitter_kwargs:
|
|
243
247
|
if (
|
|
@@ -250,7 +254,7 @@ def strip(
|
|
|
250
254
|
|
|
251
255
|
if swarm_kwargs is None:
|
|
252
256
|
swarm_kwargs = dict(corral="gutter", priority="ascending", marker_pad_px=0)
|
|
253
|
-
elif
|
|
257
|
+
elif not isinstance(swarm_kwargs, dict):
|
|
254
258
|
raise RuntimeError("`swarm_kwargs` must be a dict.")
|
|
255
259
|
if "corral" not in swarm_kwargs:
|
|
256
260
|
swarm_kwargs["corral"] = "gutter"
|
|
@@ -318,7 +322,11 @@ def strip(
|
|
|
318
322
|
if spread == "swarm":
|
|
319
323
|
r = (marker_kwargs["size"] + marker_kwargs["line_width"]) / 2
|
|
320
324
|
|
|
321
|
-
if (
|
|
325
|
+
if (
|
|
326
|
+
q_axis == "x" and "x_axis_type" in kwargs and kwargs["x_axis_type"] == "log"
|
|
327
|
+
) or (
|
|
328
|
+
q_axis == "y" and "y_axis_type" in kwargs and kwargs["y_axis_type"] == "log"
|
|
329
|
+
):
|
|
322
330
|
log_q = True
|
|
323
331
|
else:
|
|
324
332
|
log_q = False
|
|
@@ -347,12 +355,13 @@ def strip(
|
|
|
347
355
|
data[q].max() + 0.05 * q_range_width,
|
|
348
356
|
]
|
|
349
357
|
|
|
350
|
-
|
|
351
358
|
swarm_transform = (
|
|
352
|
-
grouped[q]
|
|
359
|
+
grouped[q]
|
|
360
|
+
.transform(_swarm, p, r, q_range, q_axis, log_q, **swarm_kwargs)
|
|
361
|
+
.values
|
|
353
362
|
)
|
|
354
363
|
source_dict["__swarm"] = [
|
|
355
|
-
(*cat, y_val) if
|
|
364
|
+
(*cat, y_val) if isinstance(cat, tuple) else (cat, y_val)
|
|
356
365
|
for cat, y_val in zip(source_dict["cat"], swarm_transform)
|
|
357
366
|
]
|
|
358
367
|
|
|
@@ -385,7 +394,7 @@ def strip(
|
|
|
385
394
|
if parcoord_kwargs is None:
|
|
386
395
|
line_color = "gray"
|
|
387
396
|
parcoord_kwargs = {}
|
|
388
|
-
elif
|
|
397
|
+
elif not isinstance(parcoord_kwargs, dict):
|
|
389
398
|
raise RuntimeError("`parcoord_kwargs` must be a dict.")
|
|
390
399
|
|
|
391
400
|
if "color" in parcoord_kwargs and "line_color" not in parcoord_kwargs:
|
|
@@ -431,21 +440,17 @@ def strip(
|
|
|
431
440
|
title=color_column,
|
|
432
441
|
)
|
|
433
442
|
p.add_layout(legend, legend_location)
|
|
434
|
-
elif
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
"center",
|
|
446
|
-
]
|
|
447
|
-
or type(legend_location) == tuple
|
|
448
|
-
):
|
|
443
|
+
elif legend_location in [
|
|
444
|
+
"top_left",
|
|
445
|
+
"top_center",
|
|
446
|
+
"top_right",
|
|
447
|
+
"center_right",
|
|
448
|
+
"bottom_right",
|
|
449
|
+
"bottom_center",
|
|
450
|
+
"bottom_left",
|
|
451
|
+
"center_left",
|
|
452
|
+
"center",
|
|
453
|
+
] or isinstance(legend_location, tuple):
|
|
449
454
|
legend = bokeh.models.Legend(
|
|
450
455
|
items=items,
|
|
451
456
|
location=legend_location,
|
|
@@ -523,11 +528,10 @@ def box(
|
|
|
523
528
|
suppress them. This should only be False when using the boxes
|
|
524
529
|
as annotation on another plot.
|
|
525
530
|
outlier_marker : str, default 'circle'
|
|
526
|
-
Name of marker to be used in the plot
|
|
527
|
-
|
|
528
|
-
'
|
|
529
|
-
'
|
|
530
|
-
'triangle', 'x']
|
|
531
|
+
Name of marker to be used in the plot. Must be one of
|
|
532
|
+
['asterisk', 'circle', 'circle_cross', 'circle_x', 'cross',
|
|
533
|
+
'dash', 'diamond', 'diamond_cross', 'hex', 'inverted_triangle',
|
|
534
|
+
'square', 'square_cross', 'square_x', 'triangle', 'x'].
|
|
531
535
|
min_data : int, default 5
|
|
532
536
|
Minimum number of data points in a given category in order to
|
|
533
537
|
make a box and whisker. Otherwise, individual data points are
|
|
@@ -546,12 +550,14 @@ def box(
|
|
|
546
550
|
outlier_kwargs : dict, default None
|
|
547
551
|
A dictionary of kwargs to be passed into `p.scatter()`
|
|
548
552
|
when constructing the outliers for the box plot.
|
|
553
|
+
display_outliers : bool, default None
|
|
554
|
+
Deprecated. Use `display_points`.
|
|
549
555
|
horizontal : bool or None, default None
|
|
550
556
|
Deprecated. Use `q_axis`.
|
|
551
557
|
val : hashable
|
|
552
558
|
Deprecated, use `q`.
|
|
553
559
|
kwargs
|
|
554
|
-
Kwargs that are passed to bokeh.plotting.figure() in
|
|
560
|
+
Kwargs that are passed to bokeh.plotting.figure() in constructing
|
|
555
561
|
the figure.
|
|
556
562
|
|
|
557
563
|
Returns
|
|
@@ -590,6 +596,9 @@ def box(
|
|
|
590
596
|
if palette is None:
|
|
591
597
|
palette = colorcet.b_glasbey_category10
|
|
592
598
|
|
|
599
|
+
# A box plot has no legend, so only `order` is checked here.
|
|
600
|
+
utils._check_cats_none(cats, order)
|
|
601
|
+
|
|
593
602
|
data, q, cats, _ = utils._data_cats(data, q, cats, False, None)
|
|
594
603
|
order = utils._order_to_str(order)
|
|
595
604
|
|
|
@@ -599,13 +608,13 @@ def box(
|
|
|
599
608
|
|
|
600
609
|
if outlier_kwargs is None:
|
|
601
610
|
outlier_kwargs = dict()
|
|
602
|
-
elif
|
|
611
|
+
elif not isinstance(outlier_kwargs, dict):
|
|
603
612
|
raise RuntimeError("`outlier_kwargs` must be a dict.")
|
|
604
613
|
|
|
605
614
|
if box_kwargs is None:
|
|
606
615
|
box_kwargs = {"line_color": None}
|
|
607
616
|
box_width = 0.4
|
|
608
|
-
elif
|
|
617
|
+
elif not isinstance(box_kwargs, dict):
|
|
609
618
|
raise RuntimeError("`box_kwargs` must be a dict.")
|
|
610
619
|
else:
|
|
611
620
|
box_width = box_kwargs.pop("width", 0.4)
|
|
@@ -614,14 +623,16 @@ def box(
|
|
|
614
623
|
|
|
615
624
|
if whisker_kwargs is None:
|
|
616
625
|
whisker_kwargs = {"line_color": "black"}
|
|
617
|
-
elif
|
|
626
|
+
elif not isinstance(whisker_kwargs, dict):
|
|
618
627
|
raise RuntimeError("`whisker_kwargs` must be a dict.")
|
|
628
|
+
elif "line_color" not in whisker_kwargs and "color" not in whisker_kwargs:
|
|
629
|
+
whisker_kwargs["line_color"] = "black"
|
|
619
630
|
|
|
620
631
|
if median_kwargs is None:
|
|
621
632
|
median_kwargs = {"line_color": "white"}
|
|
622
|
-
elif
|
|
633
|
+
elif not isinstance(median_kwargs, dict):
|
|
623
634
|
raise RuntimeError("`median_kwargs` must be a dict.")
|
|
624
|
-
elif "line_color" not in median_kwargs:
|
|
635
|
+
elif "color" not in median_kwargs and "line_color" not in median_kwargs:
|
|
625
636
|
median_kwargs["line_color"] = "white"
|
|
626
637
|
|
|
627
638
|
if q_axis == "x":
|
|
@@ -723,7 +734,9 @@ def box(
|
|
|
723
734
|
**median_kwargs,
|
|
724
735
|
)
|
|
725
736
|
if display_points:
|
|
726
|
-
p.scatter(
|
|
737
|
+
p.scatter(
|
|
738
|
+
source=source_outliers, y="cat", x=q, marker=marker, **outlier_kwargs
|
|
739
|
+
)
|
|
727
740
|
if not cat_grid:
|
|
728
741
|
p.ygrid.grid_line_color = None
|
|
729
742
|
else:
|
|
@@ -777,7 +790,9 @@ def box(
|
|
|
777
790
|
**median_kwargs,
|
|
778
791
|
)
|
|
779
792
|
if display_points:
|
|
780
|
-
p.scatter(
|
|
793
|
+
p.scatter(
|
|
794
|
+
source=source_outliers, x="cat", y=q, marker=marker, **outlier_kwargs
|
|
795
|
+
)
|
|
781
796
|
if not cat_grid:
|
|
782
797
|
p.xgrid.grid_line_color = None
|
|
783
798
|
|
|
@@ -808,7 +823,6 @@ def stripbox(
|
|
|
808
823
|
swarm_kwargs=None,
|
|
809
824
|
parcoord_kwargs=None,
|
|
810
825
|
whisker_caps=True,
|
|
811
|
-
display_points=True,
|
|
812
826
|
min_data=5,
|
|
813
827
|
box_kwargs=None,
|
|
814
828
|
median_kwargs=None,
|
|
@@ -880,16 +894,15 @@ def stripbox(
|
|
|
880
894
|
tooltips : list of 2-tuples
|
|
881
895
|
Specification for tooltips as per Bokeh specifications. For
|
|
882
896
|
example, if we want `col1` and `col2` tooltips, we can use
|
|
883
|
-
`tooltips=[('label 1'
|
|
897
|
+
`tooltips=[('label 1', '@col1'), ('label 2', '@col2')]`.
|
|
884
898
|
marker : str, default 'circle'
|
|
885
|
-
Name of marker to be used in the plot
|
|
886
|
-
|
|
887
|
-
'
|
|
888
|
-
'
|
|
889
|
-
'triangle', 'x']
|
|
899
|
+
Name of marker to be used in the plot. Must be one of
|
|
900
|
+
['asterisk', 'circle', 'circle_cross', 'circle_x', 'cross',
|
|
901
|
+
'dash', 'diamond', 'diamond_cross', 'hex', 'inverted_triangle',
|
|
902
|
+
'square', 'square_cross', 'square_x', 'triangle', 'x'].
|
|
890
903
|
spread : str or None, default None
|
|
891
904
|
If 'jitter', spread points out using a jitter transform. If
|
|
892
|
-
'swarm', spread points in beeswarm style.
|
|
905
|
+
'swarm', spread points in beeswarm style. If None or 'none', do
|
|
893
906
|
not spread.
|
|
894
907
|
cat_grid : bool, default False
|
|
895
908
|
If True, display grid line for categorical axis.
|
|
@@ -909,9 +922,9 @@ def stripbox(
|
|
|
909
922
|
|
|
910
923
|
- 'corral': Either 'gutter' (default) or 'wrap'. This
|
|
911
924
|
specifies how points that are moved too far out are dealt
|
|
912
|
-
with. Using 'gutter', points are
|
|
925
|
+
with. Using 'gutter', points are overlaid at the maximum
|
|
913
926
|
allowed distance. Using 'wrap', points are reflected inwards
|
|
914
|
-
|
|
927
|
+
from the maximal extent and possibly overlaid with other
|
|
915
928
|
points.
|
|
916
929
|
|
|
917
930
|
- 'priority': Either 'ascending' (default) or 'descending'.
|
|
@@ -922,7 +935,8 @@ def stripbox(
|
|
|
922
935
|
default 0.
|
|
923
936
|
parcoord_kwargs : dict
|
|
924
937
|
Keyword arguments to be passed to `p.line()` when making lines
|
|
925
|
-
for
|
|
938
|
+
for the parallel coordinate plot. Default is to have one-pixel
|
|
939
|
+
gray lines.
|
|
926
940
|
whisker_caps : bool, default True
|
|
927
941
|
If True, put caps on whiskers. If False, omit caps.
|
|
928
942
|
min_data : int, default 5
|
|
@@ -955,6 +969,10 @@ def stripbox(
|
|
|
955
969
|
output : bokeh.plotting.Figure instance
|
|
956
970
|
Plot populated with a strip-box plot.
|
|
957
971
|
"""
|
|
972
|
+
# display_points not allowed in kwargs
|
|
973
|
+
if "display_points" in kwargs:
|
|
974
|
+
raise ValueError("display_points not allowed as a kwarg for stripbox.")
|
|
975
|
+
|
|
958
976
|
# Protect against mutability of dicts
|
|
959
977
|
box_kwargs = copy.copy(box_kwargs)
|
|
960
978
|
median_kwargs = copy.copy(median_kwargs)
|
|
@@ -976,12 +994,12 @@ def stripbox(
|
|
|
976
994
|
|
|
977
995
|
if median_kwargs is None:
|
|
978
996
|
median_kwargs = dict(line_color="gray")
|
|
979
|
-
if "color" not in
|
|
997
|
+
if "color" not in median_kwargs and "line_color" not in median_kwargs:
|
|
980
998
|
median_kwargs["line_color"] = "gray"
|
|
981
999
|
|
|
982
1000
|
if whisker_kwargs is None:
|
|
983
1001
|
whisker_kwargs = dict(line_color="gray")
|
|
984
|
-
if "color" not in
|
|
1002
|
+
if "color" not in whisker_kwargs and "line_color" not in whisker_kwargs:
|
|
985
1003
|
whisker_kwargs["line_color"] = "gray"
|
|
986
1004
|
|
|
987
1005
|
if top_level == "box":
|
|
@@ -1157,7 +1175,7 @@ def striphistogram(
|
|
|
1157
1175
|
If None, create a new figure. Otherwise, populate the existing
|
|
1158
1176
|
figure `p`.
|
|
1159
1177
|
top_level : str, default 'strip'
|
|
1160
|
-
If 'histogram', the histogram is overlaid. If 'strip', the strip
|
|
1178
|
+
If 'histogram', the histogram is overlaid. If 'strip', the strip
|
|
1161
1179
|
plot is overlaid.
|
|
1162
1180
|
show_legend : bool, default False
|
|
1163
1181
|
If True, display legend.
|
|
@@ -1187,20 +1205,21 @@ def striphistogram(
|
|
|
1187
1205
|
tooltips : list of 2-tuples
|
|
1188
1206
|
Specification for tooltips as per Bokeh specifications. For
|
|
1189
1207
|
example, if we want `col1` and `col2` tooltips, we can use
|
|
1190
|
-
`tooltips=[('label 1'
|
|
1208
|
+
`tooltips=[('label 1', '@col1'), ('label 2', '@col2')]`.
|
|
1191
1209
|
marker : str, default 'circle'
|
|
1192
|
-
Name of marker to be used in the plot
|
|
1193
|
-
|
|
1194
|
-
'
|
|
1195
|
-
'
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1210
|
+
Name of marker to be used in the plot. Must be one of
|
|
1211
|
+
['asterisk', 'circle', 'circle_cross', 'circle_x', 'cross',
|
|
1212
|
+
'dash', 'diamond', 'diamond_cross', 'hex', 'inverted_triangle',
|
|
1213
|
+
'square', 'square_cross', 'square_x', 'triangle', 'x'].
|
|
1214
|
+
spread : str or None, default None
|
|
1215
|
+
If 'jitter', spread points out using a jitter transform. If
|
|
1216
|
+
'swarm', spread points in beeswarm style. If None or 'none', do
|
|
1217
|
+
not spread.
|
|
1199
1218
|
cat_grid : bool, default True
|
|
1200
1219
|
If True, display grid line for categorical axis.
|
|
1201
1220
|
marker_kwargs : dict
|
|
1202
1221
|
Keyword arguments to pass when adding markers to the plot.
|
|
1203
|
-
["x", "y", "source", "marker", "cat", "legend"] are
|
|
1222
|
+
["x", "y", "source", "marker", "cat", "legend"] are not allowed
|
|
1204
1223
|
because they are determined by other inputs.
|
|
1205
1224
|
jitter_kwargs : dict
|
|
1206
1225
|
Keyword arguments to be passed to `bokeh.transform.jitter()`. If
|
|
@@ -1214,9 +1233,9 @@ def striphistogram(
|
|
|
1214
1233
|
|
|
1215
1234
|
- 'corral': Either 'gutter' (default) or 'wrap'. This
|
|
1216
1235
|
specifies how points that are moved too far out are dealt
|
|
1217
|
-
with. Using 'gutter', points are
|
|
1236
|
+
with. Using 'gutter', points are overlaid at the maximum
|
|
1218
1237
|
allowed distance. Using 'wrap', points are reflected inwards
|
|
1219
|
-
|
|
1238
|
+
from the maximal extent and possibly overlaid with other
|
|
1220
1239
|
points.
|
|
1221
1240
|
|
|
1222
1241
|
- 'priority': Either 'ascending' (default) or 'descending'.
|
|
@@ -1227,7 +1246,8 @@ def striphistogram(
|
|
|
1227
1246
|
default 0.
|
|
1228
1247
|
parcoord_kwargs : dict
|
|
1229
1248
|
Keyword arguments to be passed to `p.line()` when making lines
|
|
1230
|
-
for
|
|
1249
|
+
for the parallel coordinate plot. Default is to have one-pixel
|
|
1250
|
+
gray lines.
|
|
1231
1251
|
bins : int, array_like, or str, default 'freedman-diaconis'
|
|
1232
1252
|
If int or array_like, setting for `bins` kwarg to be passed to
|
|
1233
1253
|
`np.histogram()`. If 'exact', then each unique value in the
|
|
@@ -1237,17 +1257,17 @@ def striphistogram(
|
|
|
1237
1257
|
`freedman-diaconis`, uses the Freedman-Diaconis rule for number
|
|
1238
1258
|
of bins.
|
|
1239
1259
|
style : None or one of ['step', 'step_filled']
|
|
1240
|
-
Default for
|
|
1241
|
-
histograms 'step_filled'. The exception is when `
|
|
1260
|
+
Default for overlaid histograms is 'step' and for stacked
|
|
1261
|
+
histograms 'step_filled'. The exception is when `conf_int` is
|
|
1242
1262
|
True, in which case `style` must be 'step'.
|
|
1243
1263
|
mirror : bool, default True
|
|
1244
1264
|
If True, reflect the histogram through zero.
|
|
1245
1265
|
hist_height : float, default 0.75
|
|
1246
|
-
Maximal height of histogram
|
|
1266
|
+
Maximal height of histogram or its confidence interval as a
|
|
1247
1267
|
fraction of available height along categorical axis. Only active
|
|
1248
1268
|
when `arrangement` is 'stack'.
|
|
1249
1269
|
conf_int : bool, default False
|
|
1250
|
-
If True, display confidence interval of
|
|
1270
|
+
If True, display confidence interval of the histogram.
|
|
1251
1271
|
ptiles : list, default (2.5, 97.5)
|
|
1252
1272
|
The percentiles to use for the confidence interval of the
|
|
1253
1273
|
histogram. Ignored if `conf_int` is False.
|
|
@@ -1262,6 +1282,8 @@ def striphistogram(
|
|
|
1262
1282
|
for the step-filled histogram or confidence intervals. Ignored
|
|
1263
1283
|
if `style = 'step'` and `conf_int` is False. By default
|
|
1264
1284
|
{"fill_alpha": 0.3, "line_alpha": 0}.
|
|
1285
|
+
jitter : bool, default False
|
|
1286
|
+
Deprecated, use `spread`.
|
|
1265
1287
|
horizontal : bool or None, default None
|
|
1266
1288
|
Deprecated. Use `q_axis`.
|
|
1267
1289
|
val : hashable
|
|
@@ -1434,7 +1456,7 @@ def _get_cat_range(df, grouped, order, color_column, q_axis):
|
|
|
1434
1456
|
else:
|
|
1435
1457
|
factors = tuple([str(key) for key in grouped.groups.keys()])
|
|
1436
1458
|
else:
|
|
1437
|
-
if
|
|
1459
|
+
if isinstance(order[0], (list, tuple)):
|
|
1438
1460
|
factors = tuple([tuple([str(k) for k in key]) for key in order])
|
|
1439
1461
|
else:
|
|
1440
1462
|
factors = tuple([str(entry) for entry in order])
|
|
@@ -1455,7 +1477,7 @@ def _get_cat_range(df, grouped, order, color_column, q_axis):
|
|
|
1455
1477
|
|
|
1456
1478
|
|
|
1457
1479
|
def _color_column_hexcodes(df, color_column):
|
|
1458
|
-
"""Return True
|
|
1480
|
+
"""Return True if the color column consists of all hex codes."""
|
|
1459
1481
|
try:
|
|
1460
1482
|
return df[color_column].str.match(r"^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$").all()
|
|
1461
1483
|
except:
|
|
@@ -1494,7 +1516,7 @@ def _cat_figure(df, grouped, q, order, color_column, q_axis, kwargs):
|
|
|
1494
1516
|
def _cat_source_dict(df, cats, cols, color_column):
|
|
1495
1517
|
cat_source, labels = utils._source_and_labels_from_cats(df, cats)
|
|
1496
1518
|
|
|
1497
|
-
if
|
|
1519
|
+
if isinstance(cols, (list, tuple, pd.Index)):
|
|
1498
1520
|
source_dict = {col: list(df[col].values) for col in cols}
|
|
1499
1521
|
else:
|
|
1500
1522
|
source_dict = {cols: list(df[cols].values)}
|
|
@@ -1510,7 +1532,7 @@ def _cat_source_dict(df, cats, cols, color_column):
|
|
|
1510
1532
|
|
|
1511
1533
|
|
|
1512
1534
|
def _parcoord_source(data, q, cats, q_axis, parcoord_column, factors):
|
|
1513
|
-
if
|
|
1535
|
+
if not isinstance(cats, (list, tuple)):
|
|
1514
1536
|
cats = [cats]
|
|
1515
1537
|
tuple_factors = False
|
|
1516
1538
|
else:
|
|
@@ -1629,7 +1651,7 @@ def _box_source(df, cats, q, cols, min_data):
|
|
|
1629
1651
|
|
|
1630
1652
|
|
|
1631
1653
|
def _out_every_interval(y, intervals, epsilon=1e-6):
|
|
1632
|
-
"""Check to see if a value `y`
|
|
1654
|
+
"""Check to see if a value `y` lies outside every interval in a
|
|
1633
1655
|
list of 2-tuples `intervals`."""
|
|
1634
1656
|
for interval in intervals:
|
|
1635
1657
|
if y > interval[0] + epsilon and y < interval[1] - epsilon:
|
|
@@ -1654,7 +1676,7 @@ def _swarm_px(
|
|
|
1654
1676
|
Parameters
|
|
1655
1677
|
----------
|
|
1656
1678
|
x : array_like
|
|
1657
|
-
Array of values of quantitative
|
|
1679
|
+
Array of values of quantitative variable.
|
|
1658
1680
|
frame_width : int or float
|
|
1659
1681
|
Width of plot frame in pixels.
|
|
1660
1682
|
r : float
|
|
@@ -1667,14 +1689,14 @@ def _swarm_px(
|
|
|
1667
1689
|
the quantitative axis.
|
|
1668
1690
|
max_y_px : float, default np.inf
|
|
1669
1691
|
Maximum allowed displacement. Any points with computed y-values
|
|
1670
|
-
beyond this will be
|
|
1692
|
+
beyond this will be corralled.
|
|
1671
1693
|
corral : str, default 'gutter'
|
|
1672
1694
|
Either 'gutter' or 'wrap'. How to corral points beyond the
|
|
1673
1695
|
maximum displacement.
|
|
1674
|
-
priority : str,
|
|
1696
|
+
priority : str, default 'ascending'
|
|
1675
1697
|
Sort order when determining which points get moved in the
|
|
1676
1698
|
y-direction first. Either 'ascending' or 'descending'.
|
|
1677
|
-
marker_pad_px : int
|
|
1699
|
+
marker_pad_px : int or float
|
|
1678
1700
|
Gap between markers in units of pixels.
|
|
1679
1701
|
|
|
1680
1702
|
Returns
|
|
@@ -1709,7 +1731,7 @@ def _swarm_px(
|
|
|
1709
1731
|
else:
|
|
1710
1732
|
continue
|
|
1711
1733
|
if y_pixels[j] < np.inf:
|
|
1712
|
-
offset = np.sqrt(4 * r
|
|
1734
|
+
offset = np.sqrt(4 * r**2 - dist**2) + marker_pad_px
|
|
1713
1735
|
intervals.append([y_pixels[j] - offset, y_pixels[j] + offset])
|
|
1714
1736
|
|
|
1715
1737
|
# Scan points to the left
|
|
@@ -1721,11 +1743,11 @@ def _swarm_px(
|
|
|
1721
1743
|
else:
|
|
1722
1744
|
continue
|
|
1723
1745
|
if y_pixels[j] < np.inf:
|
|
1724
|
-
offset = np.sqrt(4 * r
|
|
1746
|
+
offset = np.sqrt(4 * r**2 - dist**2) + marker_pad_px
|
|
1725
1747
|
intervals.append([y_pixels[j] - offset, y_pixels[j] + offset])
|
|
1726
1748
|
|
|
1727
1749
|
# Any y-position must be outside all intervals and should be at the edge of one of the intervals
|
|
1728
|
-
# Need to find first candidate
|
|
1750
|
+
# Need to find the first candidate that satisfies this
|
|
1729
1751
|
y_cand = 0
|
|
1730
1752
|
if len(intervals) > 0:
|
|
1731
1753
|
candidates = sorted(np.array(intervals).flatten(), key=abs)
|
|
@@ -1754,11 +1776,19 @@ def _swarm_px(
|
|
|
1754
1776
|
|
|
1755
1777
|
|
|
1756
1778
|
def _swarm(
|
|
1757
|
-
x,
|
|
1779
|
+
x,
|
|
1780
|
+
p,
|
|
1781
|
+
r,
|
|
1782
|
+
x_range,
|
|
1783
|
+
q_axis,
|
|
1784
|
+
log_q,
|
|
1785
|
+
corral="gutter",
|
|
1786
|
+
priority="ascending",
|
|
1787
|
+
marker_pad_px=0,
|
|
1758
1788
|
):
|
|
1759
1789
|
if q_axis == "x":
|
|
1760
1790
|
extra_padding = 0
|
|
1761
|
-
if
|
|
1791
|
+
if isinstance(p.y_range.factors[0], tuple):
|
|
1762
1792
|
if len(p.y_range.factors[0]) >= 2:
|
|
1763
1793
|
extra_padding += p.y_range.group_padding
|
|
1764
1794
|
if len(p.y_range.factors[0]) > 2:
|
|
@@ -1770,7 +1800,7 @@ def _swarm(
|
|
|
1770
1800
|
n_factors = len(p.y_range.factors) + extra_padding
|
|
1771
1801
|
else:
|
|
1772
1802
|
extra_padding = 0
|
|
1773
|
-
if
|
|
1803
|
+
if isinstance(p.x_range.factors[0], tuple):
|
|
1774
1804
|
if len(p.x_range.factors[0]) >= 2:
|
|
1775
1805
|
extra_padding += p.x_range.group_padding
|
|
1776
1806
|
if len(p.x_range.factors[0]) > 2:
|