Skip to content

Commit

Permalink
Fixed nested categorical sort order (#3242)
Browse files Browse the repository at this point in the history
  • Loading branch information
philippjfr committed Dec 3, 2018
1 parent 8e8805a commit 966d99b
Show file tree
Hide file tree
Showing 5 changed files with 31 additions and 5 deletions.
3 changes: 2 additions & 1 deletion holoviews/plotting/bokeh/chart.py
Expand Up @@ -816,8 +816,9 @@ def _get_factors(self, element):
for x in xvals]
if gdim and not sdim:
gvals = element.dimension_values(gdim, False)
gvals = [g if gvals.dtype.kind in 'SU' else gdim.pprint_value(g) for g in gvals]
xvals = sorted([(x, g) for x in xvals for g in gvals])
is_str = gvals.dtype.kind in 'SU'
xvals = [(x, g if is_str else gdim.pprint_value(g)) for (x, g) in xvals]
coords = xvals, []
if self.invert_axes: coords = coords[::-1]
return coords
Expand Down
9 changes: 5 additions & 4 deletions holoviews/plotting/bokeh/stats.py
Expand Up @@ -118,12 +118,13 @@ def _get_factors(self, element):
if not element.kdims:
xfactors, yfactors = [element.label], []
else:
factors = [tuple(d.pprint_value(v) for d, v in zip(element.kdims, key))
for key in element.groupby(element.kdims).data.keys()]
factors = [key for key in element.groupby(element.kdims).data.keys()]
if element.ndims > 1:
factors = sorted(factors)
factors = [tuple(d.pprint_value(k) for d, k in zip(element.kdims, key))
for key in factors]
factors = [f[0] if len(f) == 1 else f for f in factors]
xfactors, yfactors = factors, []
if element.ndims > 1:
xfactors = sorted(xfactors)
return (yfactors, xfactors) if self.invert_axes else (xfactors, yfactors)

def _postprocess_hover(self, renderer, source):
Expand Down
8 changes: 8 additions & 0 deletions holoviews/tests/plotting/bokeh/testbarplot.py
Expand Up @@ -48,6 +48,14 @@ def test_bars_grouped_categories(self):
x_range = plot.handles['x_range']
self.assertEqual(x_range.factors, [('A', '0'), ('A', '1'), ('B', '0'), ('B', '1')])

def test_box_whisker_multi_level_sorted(self):
box= Bars((['A', 'B']*15, [3, 10, 1]*10, np.random.randn(30)),
['Group', 'Category'], 'Value').aggregate(function=np.mean)
plot = bokeh_renderer.get_plot(box)
x_range = plot.handles['x_range']
self.assertEqual(x_range.factors, [
('A', '1'), ('A', '3'), ('A', '10'), ('B', '1'), ('B', '3'), ('B', '10')])

def test_bars_positive_negative_mixed(self):
bars = Bars([('A', 0, 1), ('A', 1, -1), ('B', 0, 2)],
kdims=['Index', 'Category'], vdims=['Value'])
Expand Down
8 changes: 8 additions & 0 deletions holoviews/tests/plotting/bokeh/testboxwhiskerplot.py
Expand Up @@ -36,6 +36,14 @@ def test_box_whisker_hover(self):
self.assertIn(plot.handles['vbar_2_glyph_renderer'], hover_tool.renderers)
self.assertIn(plot.handles['circle_1_glyph_renderer'], hover_tool.renderers)

def test_box_whisker_multi_level(self):
box= BoxWhisker((['A', 'B']*15, [3, 10, 1]*10, np.random.randn(30)),
['Group', 'Category'], 'Value')
plot = bokeh_renderer.get_plot(box)
x_range = plot.handles['x_range']
self.assertEqual(x_range.factors, [
('A', '1'), ('A', '3'), ('A', '10'), ('B', '1'), ('B', '3'), ('B', '10')])

def test_box_whisker_padding_square(self):
curve = BoxWhisker([1, 2, 3]).options(padding=0.1)
plot = bokeh_renderer.get_plot(curve)
Expand Down
8 changes: 8 additions & 0 deletions holoviews/tests/plotting/bokeh/testviolinplot.py
Expand Up @@ -47,6 +47,14 @@ def test_violin_simple(self):
self.assertEqual(patch_source.data['xs'], [kde['y']])
self.assertEqual(patch_source.data['ys'], [kde['x']])

def test_box_whisker_multi_level(self):
box= Violin((['A', 'B']*15, [3, 10, 1]*10, np.random.randn(30)),
['Group', 'Category'], 'Value')
plot = bokeh_renderer.get_plot(box)
x_range = plot.handles['x_range']
self.assertEqual(x_range.factors, [
('A', '1'), ('A', '3'), ('A', '10'), ('B', '1'), ('B', '3'), ('B', '10')])

def test_violin_inner_quartiles(self):
values = np.random.rand(100)
violin = Violin(values).opts(plot=dict(inner='quartiles'))
Expand Down

0 comments on commit 966d99b

Please sign in to comment.