You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
align() outer join returns DataArrays that are all NaNs #2215
The problem occurs for me in the midst of a data-processing pipeline that starts with some ~40MB netCDF files. I've tried to create pasteable code that reproduces the behavior from scratch, but I haven't succeeded.
Problem description
I pass two DataArrays to xr.align() with join="outer". The DataArrays are dtype float64, and contain a mix of NaNs and floats. They are 2D and have MultiIndexes with some numeric and some string levels.
The tuple of DataArrays returned by align() have the correct shape and expected indexes, but the contents of the arrays are all NaNs. The original float values are gone. np.nonzero(~np.isnan(da)) returns an empty array.
I've set breakpoints and delved into the code. On line 656 in xarray.core.variable.Variable._getitem_with_mask, self contains non-NaN values, but the data returned by as_indexable(self._data)[actual_indexer] evaluates as all NaNs. However, data.array at that point (which is xarray.backends.netCDF4_.NetCDF4ArrayWrapper) has non-NaNs. So it's some sort of masking caused by the indexing that makes it look like data is all NaNs.
Expected Output
A tuple of DataArrays which contain some non-NaN values.
I found a way to reproduce the error. One of the MuliIndex levels on the DataArrays has NaNs in it. If I remove that level, the correct values appear in the result. Should the presence of that MultiIndex level cause this behavior?
import string
import numpy as np
import xarray as xr
dims = ("x", "y")
shape = (10, 5)
das = []
for j in (0, 1):
data = np.full(shape, np.nan, dtype="float64")
for i in range(shape[0]):
data[i, i % shape[1]] = float(i)
coords_d = {
"ints": ("x", range(j*shape[0], (j+1)*shape[0])),
"nans": ("x", np.array([np.nan] * shape[0], dtype="float64")),
"lower": ("y", list(string.ascii_lowercase[:shape[1]]))
}
da = xr.DataArray(data=data, dims=dims, coords=coords_d)
da.set_index(append=True, inplace=True, x=["ints", "nans"], y=["lower"])
das.append(da)
nonzeros_raw = [np.nonzero(~np.isnan(da)) for da in das]
print("nonzeros_raw: ")
print(nonzeros_raw)
aligned = xr.align(*das, join="outer")
nonzeros_aligned = [np.nonzero(~np.isnan(da)) for da in aligned]
print("nonzeros_aligned: ")
print(nonzeros_aligned)
assert nonzeros_raw[0].shape == nonzeros_aligned[0].shape
Since the align is an outer join, I would expect all the non-NaN values in the original DataArrays to also appear in the aligned DataArrays. Perhaps I am misinterpreting the behavior of join="outer".
Since the align is an outer join, I would expect all the non-NaN values in the original DataArrays to also appear in the aligned DataArrays.
Sorry, I'm not quite following -- can we please give a specific example of which output from your example looks wrong, and print how it should look instead?
I see something very similar, but with the nans level removed, if I do this: xr.align(*[da.reset_index("nans", drop=True) for da in das], join="outer")
The only material difference I can see in our environments is that I'm running pandas 0.23 and you're running pandas 0.22. Can you try updating pandas and see if that fixes the issue?
@shoyer That did it. Under pandas 0.22, the DataArrays in aligned are all NaNs. I updated to pandas 0.23, and the non-NaN values were there as expected. To double-check, I downgraded to 0.22 again and got all NaNs again.
Activity
shoyer commentedon Jun 5, 2018
Are you sure the indexes along the aligned dimensions match exactly? Small differences in floats are the most common source of this issue.
Try using
second.reindex_like(first, method='nearest')instead ofxarray.align(first, second).jjpr-mit commentedon Jun 5, 2018
I found a way to reproduce the error. One of the MuliIndex levels on the DataArrays has NaNs in it. If I remove that level, the correct values appear in the result. Should the presence of that MultiIndex level cause this behavior?
shoyer commentedon Jun 5, 2018
Thanks for the example. Can you please identify exactly which behavior you find surprising, and what you think the result should be?
jjpr-mit commentedon Jun 5, 2018
Since the align is an outer join, I would expect all the non-NaN values in the original DataArrays to also appear in the aligned DataArrays. Perhaps I am misinterpreting the behavior of
join="outer".jjpr-mit commentedon Jun 5, 2018
For clarity, here are the prints of the arrays before and after alignment:
Before alignment:
After alignment:
shoyer commentedon Jun 5, 2018
Sorry, I'm not quite following -- can we please give a specific example of which output from your example looks wrong, and print how it should look instead?
jjpr-mit commentedon Jun 5, 2018
This is what I would expect to see returned by align():
I see something very similar, but with the
nanslevel removed, if I do this:xr.align(*[da.reset_index("nans", drop=True) for da in das], join="outer")shoyer commentedon Jun 6, 2018
This what I see when printing
alignedfrom your example:The only material difference I can see in our environments is that I'm running pandas 0.23 and you're running pandas 0.22. Can you try updating pandas and see if that fixes the issue?
jjpr-mit commentedon Jun 13, 2018
@shoyer That did it. Under pandas 0.22, the DataArrays in
alignedare all NaNs. I updated to pandas 0.23, and the non-NaN values were there as expected. To double-check, I downgraded to 0.22 again and got all NaNs again.shoyer commentedon Jun 13, 2018
OK, great. I'm going to close this then, and simply recommend that anyone encounter this issue try upgrading pandas.
A much simplified way to reproduce the bug. Submitted as part of pyda…