Repository: holoviz/holoviews

Issue:
Conversion of xarray to BoxWhisker breaks coordinate ordering
With an xarray Dataset `xarr` with a categorical coordinate `label` and a data variable `value`, I have reordered the coordinate labels to have a particular order. If I apply
```
xarr.to(hv.Scatter, [`label`], [`value`])
```
the categorical labels are in the correct order along the x-axis. If I do  
```
xarr.to(hv.BoxWhisker, [`label`], [`value`])
```
instead, then the labels appear in a different (seemingly alphabetical) order. There is a `FutureWarning` which hints at issues with preserving key order: 

```
/home/name/anaconda3/envs/tftt/lib/python3.5/site-packages/holoviews/core/data/pandas.py:130: FutureWarning: from_items is deprecated. Please use DataFrame.from_dict(dict(items), ...) instead. DataFrame.from_dict(OrderedDict(items)) may be used to preserve the key order.
  zip(columns, data)])
```

Is there a way to reorder the categorical labels of an axis post hoc?


Discussion:
I am not sure where this is documented, but with some guesswork I found
```
xarr.to(hv.BoxWhisker, [`label`], [`value`]).redim.values(label=new_order)
```
to function as a workaround, for anyone affected in the future.

Resolving patch:
diff --git a/holoviews/plotting/bokeh/stats.py b/holoviews/plotting/bokeh/stats.py
--- a/holoviews/plotting/bokeh/stats.py
+++ b/holoviews/plotting/bokeh/stats.py
@@ -7,6 +7,7 @@
 from bokeh.models import FactorRange, Circle, VBar, HBar
 
 from ...core.dimension import Dimension
+from ...core.ndmapping import sorted_context
 from ...core.util import (basestring, dimension_sanitizer, wrap_tuple,
                           unique_iterator)
 from ...operation.stats import univariate_kde
@@ -121,7 +122,8 @@ def _postprocess_hover(self, renderer, source):
 
     def get_data(self, element, ranges, style):
         if element.kdims:
-            groups = element.groupby(element.kdims).data
+            with sorted_context(False):
+                groups = element.groupby(element.kdims).data
         else:
             groups = dict([(element.label, element)])
         vdim = dimension_sanitizer(element.vdims[0].name)
@@ -364,7 +366,8 @@ def _kde_data(self, el, key, **kwargs):
 
     def get_data(self, element, ranges, style):
         if element.kdims:
-            groups = element.groupby(element.kdims).data
+            with sorted_context(False):
+                groups = element.groupby(element.kdims).data
         else:
             groups = dict([((element.label,), element)])
 
diff --git a/holoviews/plotting/mpl/stats.py b/holoviews/plotting/mpl/stats.py
--- a/holoviews/plotting/mpl/stats.py
+++ b/holoviews/plotting/mpl/stats.py
@@ -1,6 +1,7 @@
 import param
 import numpy as np
 
+from ...core.ndmapping import sorted_context
 from .chart import AreaPlot, ChartPlot
 from .path import PolygonPlot
 from .plot import AdjoinedPlot
@@ -64,7 +65,8 @@ def get_extents(self, element, ranges):
 
 
     def get_data(self, element, ranges, style):
-        groups = element.groupby(element.kdims)
+        with sorted_context(False):
+            groups = element.groupby(element.kdims)
 
         data, labels = [], []
 
@@ -173,7 +175,8 @@ def init_artists(self, ax, plot_args, plot_kwargs):
         return artists
 
     def get_data(self, element, ranges, style):
-        groups = element.groupby(element.kdims)
+        with sorted_context(False):
+            groups = element.groupby(element.kdims)
 
         data, labels, colors = [], [], []
         elstyle = self.lookup_options(element, 'style')


Test patch: