Repository: pydata/xarray

Issue:
"_center" postfix on axis label resulting from groupby_bins persists after renaming variable


**What happened**:

I used groupby_bins + sum  to reduce the resolution of my dataset along 'x' dimension. I didn't like the 'x_bins_center' label, so I renamed the x-axis dim/coord to simply 'x.'  However, the "_center" postfix is not part of the variable name -- it appears to be some tweaking of the x-axis label when plotting. So now I am stuck with "_center" tagged at the end of the x-axis label, even after the units.  

**What you expected to happen**:

It would make more sense if the '_center' were part of the variable name.  That way, the name displayed on the plot is the same one that I need to access the variable in the dataset. Also, when I rename the variable, I will be able to change the way it displays. Furthermore, that will prevent the issue with "_center" getting pasted on after the units.

**Minimal Complete Verifiable Example**:

```python

import xarray as xr
import numpy as np
data_vars={'y':('x',np.ones((101)),{'units':'kg/m'})}
coords={'x':('x',np.linspace(0,1,101,endpoint=True),{'units':'m'})}
ds = xr.Dataset(data_vars,coords)
dsd = ds.groupby_bins('x',np.linspace(0,1,11,endpoint=True),right=False).sum(dim='x')
dsd.y.plot() #Shows that the x-axis is named "x_bins_center"
dsd = dsd.rename({'x_bins_center':'x'}) #Fails: 
>ValueError: cannot rename 'x_bins_center' because it is not a variable or dimension in this dataset
dsd = dsd.rename({'x_bins':'x'}) #Succeeds, b/c the variable is ACTUALLY named 'x_bins'
dsd.x.attrs['units']='m'
dsd.y.plot() #x-axis label is "x [m]_center"  -- there's a sneaky renaming thing that is appending _center to the end of the label

```

**Anything else we need to know?**:

<details><summary>Plots</summary>
Here's the 1st plot showing the default x-axis label prior to renaming:

![Original_plot](https://user-images.githubusercontent.com/23484003/89687789-aa88e580-d8b5-11ea-9553-a497eff5f238.png)

Here's the 2nd plot showing the mangled x-axis label after I renamed the variable & reestablished the units:

![Butchered_plot](https://user-images.githubusercontent.com/23484003/89687915-efad1780-d8b5-11ea-9348-f7016325e377.png)

</details>

**Environment**:

<details><summary>Output of <tt>xr.show_versions()</tt></summary>


INSTALLED VERSIONS
------------------
commit: None
python: 3.7.7 (default, Mar 23 2020, 17:31:31) 
[Clang 4.0.1 (tags/RELEASE_401/final)]
python-bits: 64
OS: Darwin
OS-release: 19.6.0
machine: x86_64
processor: i386
byteorder: little
LC_ALL: en_US.UTF-8
LANG: en_US.UTF-8
LOCALE: en_US.UTF-8
libhdf5: 1.10.4
libnetcdf: 4.6.1

xarray: 0.16.0
pandas: 1.0.3
numpy: 1.18.1
scipy: 1.4.1
netCDF4: 1.4.2
pydap: None
h5netcdf: 0.8.0
h5py: 2.10.0
Nio: None
zarr: None
cftime: 1.2.1
nc_time_axis: None
PseudoNetCDF: None
rasterio: None
cfgrib: None
iris: None
bottleneck: None
dask: 2.20.0
distributed: None
matplotlib: 3.1.3
cartopy: None
seaborn: None
numbagg: None
pint: 0.11
setuptools: 49.2.0.post20200714
pip: 20.1.1
conda: None
pytest: 5.4.1
IPython: 7.13.0
sphinx: 3.1.2


</details>


Discussion:

Patch:
diff --git a/doc/whats-new.rst b/doc/whats-new.rst
index c969453b..f1137b7b 100644
--- a/doc/whats-new.rst
+++ b/doc/whats-new.rst
@@ -68,6 +68,8 @@ Bug fixes
   By `Alessandro Amici <https://github.com/alexamici>`_
 - Limit number of data rows when printing large datasets. (:issue:`4736`, :pull:`4750`). By `Jimmy Westling <https://github.com/illviljan>`_.
 - Add ``missing_dims`` parameter to transpose (:issue:`4647`, :pull:`4767`). By `Daniel Mesejo <https://github.com/mesejo>`_.
+- Resolve intervals before appending other metadata to labels when plotting (:issue:`4322`, :pull:`4794`).
+  By `Justus Magin <https://github.com/keewis>`_.
 
 Documentation
 ~~~~~~~~~~~~~
diff --git a/xarray/core/missing.py b/xarray/core/missing.py
index 477c7f40..8d112b46 100644
--- a/xarray/core/missing.py
+++ b/xarray/core/missing.py
@@ -730,6 +730,13 @@ def interp_func(var, x, new_x, method, kwargs):
         # if usefull, re-use localize for each chunk of new_x
         localize = (method in ["linear", "nearest"]) and (new_x[0].chunks is not None)
 
+        # scipy.interpolate.interp1d always forces to float.
+        # Use the same check for blockwise as well:
+        if not issubclass(var.dtype.type, np.inexact):
+            dtype = np.float_
+        else:
+            dtype = var.dtype
+
         return da.blockwise(
             _dask_aware_interpnd,
             out_ind,
@@ -738,7 +745,7 @@ def interp_func(var, x, new_x, method, kwargs):
             interp_kwargs=kwargs,
             localize=localize,
             concatenate=True,
-            dtype=var.dtype,
+            dtype=dtype,
             new_axes=new_axes,
         )
 
diff --git a/xarray/plot/facetgrid.py b/xarray/plot/facetgrid.py
index 8ed8815a..58b38251 100644
--- a/xarray/plot/facetgrid.py
+++ b/xarray/plot/facetgrid.py
@@ -306,9 +306,11 @@ class FacetGrid:
                 )
                 self._mappables.append(mappable)
 
-        _, _, hueplt, xlabel, ylabel, huelabel = _infer_line_data(
+        xplt, yplt, hueplt, huelabel = _infer_line_data(
             darray=self.data.loc[self.name_dicts.flat[0]], x=x, y=y, hue=hue
         )
+        xlabel = label_from_attrs(xplt)
+        ylabel = label_from_attrs(yplt)
 
         self._hue_var = hueplt
         self._hue_label = huelabel
diff --git a/xarray/plot/plot.py b/xarray/plot/plot.py
index 2f10240e..8a57e17e 100644
--- a/xarray/plot/plot.py
+++ b/xarray/plot/plot.py
@@ -107,10 +107,7 @@ def _infer_line_data(darray, x, y, hue):
         huelabel = label_from_attrs(darray[huename])
         hueplt = darray[huename]
 
-    xlabel = label_from_attrs(xplt)
-    ylabel = label_from_attrs(yplt)
-
-    return xplt, yplt, hueplt, xlabel, ylabel, huelabel
+    return xplt, yplt, hueplt, huelabel
 
 
 def plot(
@@ -292,12 +289,14 @@ def line(
         assert "args" not in kwargs
 
     ax = get_axis(figsize, size, aspect, ax)
-    xplt, yplt, hueplt, xlabel, ylabel, hue_label = _infer_line_data(darray, x, y, hue)
+    xplt, yplt, hueplt, hue_label = _infer_line_data(darray, x, y, hue)
 
     # Remove pd.Intervals if contained in xplt.values and/or yplt.values.
-    xplt_val, yplt_val, xlabel, ylabel, kwargs = _resolve_intervals_1dplot(
-        xplt.values, yplt.values, xlabel, ylabel, kwargs
+    xplt_val, yplt_val, x_suffix, y_suffix, kwargs = _resolve_intervals_1dplot(
+        xplt.values, yplt.values, kwargs
     )
+    xlabel = label_from_attrs(xplt, extra=x_suffix)
+    ylabel = label_from_attrs(yplt, extra=y_suffix)
 
     _ensure_plottable(xplt_val, yplt_val)
 
diff --git a/xarray/plot/utils.py b/xarray/plot/utils.py
index 3eca90a1..16c67e15 100644
--- a/xarray/plot/utils.py
+++ b/xarray/plot/utils.py
@@ -503,12 +503,14 @@ def _interval_to_double_bound_points(xarray, yarray):
     return xarray, yarray
 
 
-def _resolve_intervals_1dplot(xval, yval, xlabel, ylabel, kwargs):
+def _resolve_intervals_1dplot(xval, yval, kwargs):
     """
     Helper function to replace the values of x and/or y coordinate arrays
     containing pd.Interval with their mid-points or - for step plots - double
     points which double the length.
     """
+    x_suffix = ""
+    y_suffix = ""
 
     # Is it a step plot? (see matplotlib.Axes.step)
     if kwargs.get("drawstyle", "").startswith("steps-"):
@@ -534,13 +536,13 @@ def _resolve_intervals_1dplot(xval, yval, xlabel, ylabel, kwargs):
         # Convert intervals to mid points and adjust labels
         if _valid_other_type(xval, [pd.Interval]):
             xval = _interval_to_mid_points(xval)
-            xlabel += "_center"
+            x_suffix = "_center"
         if _valid_other_type(yval, [pd.Interval]):
             yval = _interval_to_mid_points(yval)
-            ylabel += "_center"
+            y_suffix = "_center"
 
     # return converted arguments
-    return xval, yval, xlabel, ylabel, kwargs
+    return xval, yval, x_suffix, y_suffix, kwargs
 
 
 def _resolve_intervals_2dplot(val, func_name):


Test patch:
diff --git a/xarray/tests/test_missing.py b/xarray/tests/test_missing.py
index 21d82b19..2ab3508b 100644
--- a/xarray/tests/test_missing.py
+++ b/xarray/tests/test_missing.py
@@ -370,6 +370,20 @@ def test_interpolate_dask_raises_for_invalid_chunk_dim():
         da.interpolate_na("time")
 
 
+@requires_dask
+@requires_scipy
+@pytest.mark.parametrize("dtype, method", [(int, "linear"), (int, "nearest")])
+def test_interpolate_dask_expected_dtype(dtype, method):
+    da = xr.DataArray(
+        data=np.array([0, 1], dtype=dtype),
+        dims=["time"],
+        coords=dict(time=np.array([0, 1])),
+    ).chunk(dict(time=2))
+    da = da.interp(time=np.array([0, 0.5, 1, 2]), method=method)
+
+    assert da.dtype == da.compute().dtype
+
+
 @requires_bottleneck
 def test_ffill():
     da = xr.DataArray(np.array([4, 5, np.nan], dtype=np.float64), dims="x")
diff --git a/xarray/tests/test_plot.py b/xarray/tests/test_plot.py
index 2f4a4edd..471bbb70 100644
--- a/xarray/tests/test_plot.py
+++ b/xarray/tests/test_plot.py
@@ -592,6 +592,20 @@ class TestPlot(PlotTestCase):
         bins = [-1, 0, 1, 2]
         self.darray.groupby_bins("dim_0", bins).mean(...).dim_0_bins.plot()
 
+    @pytest.mark.parametrize("dim", ("x", "y"))
+    def test_labels_with_units_with_interval(self, dim):
+        """Test line plot with intervals and a units attribute."""
+        bins = [-1, 0, 1, 2]
+        arr = self.darray.groupby_bins("dim_0", bins).mean(...)
+        arr.dim_0_bins.attrs["units"] = "m"
+
+        (mappable,) = arr.plot(**{dim: "dim_0_bins"})
+        ax = mappable.figure.gca()
+        actual = getattr(ax, f"get_{dim}label")()
+
+        expected = "dim_0_bins_center [m]"
+        assert actual == expected
+
 
 class TestPlot1D(PlotTestCase):
     @pytest.fixture(autouse=True)