Repository: holoviz/hvplot

Issue:
Sorting non-categorical axis by
Not sure whether this is an an hvplot issue or a holoviews issue, but there doesn't seem to be any sorting for non-cat `by` at least for violin plots.

```python
import xarray as xr
import hvplot.xarrray

ds = xr.tutorial.open_dataset('air_temperature')
ds.hvplot.violin('air', by='lat', c='lat', cmap='fire')
```

<img width="1011" alt="Screen Shot 2019-09-24 at 3 31 33 PM" src="https://user-images.githubusercontent.com/4806877/65544049-75afb200-dee0-11e9-93d9-3b5fde9fd779.png">

Compared to the [docs](https://hvplot.pyviz.org/user_guide/Gridded_Data.html): 

<img width="1071" alt="Screen Shot 2019-09-24 at 3 33 36 PM" src="https://user-images.githubusercontent.com/4806877/65544178-b60f3000-dee0-11e9-835c-76441cabd365.png">




Discussion:
It's this logic that's doing it:

```python
if self.sort_date and self.datatype == 'pandas':
    from pandas.api.types import is_datetime64_any_dtype as is_datetime
    if x in self.indexes:
        index = self.indexes.index(x)
        if is_datetime(data.axes[index]):
            data = data.sort_index(axis=self.indexes.index(x))
    elif x in data.columns:
        if is_datetime(data[x]):
            data = data.sort_values(x)
```

We shouldn't sort by columns not being used.

Resolving patch:
diff --git a/hvplot/converter.py b/hvplot/converter.py
--- a/hvplot/converter.py
+++ b/hvplot/converter.py
@@ -1106,8 +1106,10 @@ def single_chart(self, element, x, y, data=None):
             chart = element(data, kdims, vdims).relabel(**self._relabel)
         return chart.redim(**self._redim).opts(opts)
 
-    def _process_chart_args(self, data, x, y, single_y=False):
-        data = self.data if data is None else data
+    def _process_chart_x(self, data, x):
+        """This should happen before _process_chart_y"""
+        if x is False:
+            return None
 
         x = x or self.x
         if x is None:
@@ -1115,19 +1117,13 @@ def _process_chart_args(self, data, x, y, single_y=False):
                 x = self.indexes[0]
             else:
                 x = [c for c in data.columns if c not in self.by+self.groupby][0]
-        elif not x:
-            raise ValueError('Could not determine what to plot. Expected '
-                             'x to be declared or use_index to be enabled.')
-        if self.sort_date and self.datatype == 'pandas':
-            from pandas.api.types import is_datetime64_any_dtype as is_datetime
-            if x in self.indexes:
-                index = self.indexes.index(x)
-                if is_datetime(data.axes[index]):
-                    data = data.sort_index(axis=self.indexes.index(x))
-            elif x in data.columns:
-                if is_datetime(data[x]):
-                    data = data.sort_values(x)
 
+        if not x:
+            raise ValueError('Could not determine what to plot. Set x explicitly')
+        return x
+
+    def _process_chart_y(self, data, x, y, single_y):
+        """This should happen after _process_chart_x"""
         y = y or self.y
         if y is None:
             ys = [c for c in data.columns if c not in [x]+self.by+self.groupby]
@@ -1138,7 +1134,26 @@ def _process_chart_args(self, data, x, y, single_y=False):
                 if len(num_ys) >= 1:
                     ys = num_ys
             y = ys[0] if len(ys) == 1 or single_y else ys
+        return y
+
+    def _process_chart_args(self, data, x, y, single_y=False):
+        data = self.data if data is None else data
+
+        x = self._process_chart_x(data, x)
+        y = self._process_chart_y(data, x, y, single_y)
+
+        # sort by date if enabled and x is a date
+        if x is not None and self.sort_date and self.datatype == 'pandas':
+            from pandas.api.types import is_datetime64_any_dtype as is_datetime
+            if x in self.indexes:
+                index = self.indexes.index(x)
+                if is_datetime(data.axes[index]):
+                    data = data.sort_index(axis=self.indexes.index(x))
+            elif x in data.columns:
+                if is_datetime(data[x]):
+                    data = data.sort_values(x)
 
+        # set index to column if needed in hover_cols
         if self.use_index and any(c for c in self.hover_cols if
                                   c in self.indexes and
                                   c not in data.columns):
@@ -1260,7 +1275,7 @@ def _stats_plot(self, element, y, data=None):
         """
         Helper method to generate element from indexed dataframe.
         """
-        data, x, y = self._process_chart_args(data, None, y)
+        data, x, y = self._process_chart_args(data, False, y)
 
         opts = {'plot': dict(self._plot_opts), 'norm': self._norm_opts,
                 'style': self._style_opts}


Test patch: