Repository navigation
more upstream-dev cftime failures #3751
Copy link
Copy link
Closed
Description
46 failed tests but they all seem to result from the same TypeError
=================================== FAILURES ===================================
______________ test_sel_date_scalar_nearest[365_day-sel_kwargs0] _______________
da = <xarray.DataArray (time: 4)>
0002-02-01 00:00:00],
dtype='object')
sel_kwargs = {'method': 'nearest'}
@requires_cftime
@pytest.mark.parametrize(
"sel_kwargs",
[{"method": "nearest"}, {"method": "nearest", "tolerance": timedelta(days=70)}],
)
def test_sel_date_scalar_nearest(da, date_type, index, sel_kwargs):
expected = xr.DataArray(2).assign_coords(time=index[1])
> result = da.sel(time=date_type(1, 4, 1), **sel_kwargs)
xarray/tests/test_cftimeindex.py:460:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
xarray/core/dataarray.py:1056: in sel
ds = self._to_temp_dataset().sel(
xarray/core/dataset.py:2056: in sel
pos_indexers, new_indexes = remap_label_indexers(
xarray/core/coordinates.py:391: in remap_label_indexers
pos_indexers, new_indexes = indexing.remap_label_indexers(
xarray/core/indexing.py:270: in remap_label_indexers
idxr, new_idx = convert_label_indexer(index, label, dim, method, tolerance)
xarray/core/indexing.py:189: in convert_label_indexer
indexer = index.get_loc(
xarray/coding/cftimeindex.py:334: in get_loc
return pd.Index.get_loc(self, key, method=method, tolerance=tolerance)
/usr/share/miniconda/envs/xarray-tests/lib/python3.8/site-packages/pandas/core/indexes/base.py:2899: in get_loc
indexer = self.get_indexer([key], method=method, tolerance=tolerance)
/usr/share/miniconda/envs/xarray-tests/lib/python3.8/site-packages/pandas/core/indexes/base.py:2992: in get_indexer
indexer = self._get_nearest_indexer(target, limit, tolerance)
/usr/share/miniconda/envs/xarray-tests/lib/python3.8/site-packages/pandas/core/indexes/base.py:3076: in _get_nearest_indexer
left_distances = np.abs(self[left_indexer] - target)
xarray/coding/cftimeindex.py:444: in __sub__
return CFTimeIndex(np.array(self) - other)
xarray/coding/cftimeindex.py:248: in __new__
assert_all_valid_date_type(data)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
data = TimedeltaIndex(['-59 days'], dtype='timedelta64[ns]', freq=None)
def assert_all_valid_date_type(data):
import cftime
if len(data) > 0:
sample = data[0]
date_type = type(sample)
if not isinstance(sample, cftime.datetime):
> raise TypeError(
"CFTimeIndex requires cftime.datetime "
"objects. Got object of {}.".format(date_type)
)
E TypeError: CFTimeIndex requires cftime.datetime objects. Got object of <class 'pandas._libs.tslibs.timedeltas.Timedelta'>.
xarray/coding/cftimeindex.py:206: TypeError
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
No labels
Activity
spencerkclark commentedon Feb 6, 2020
Part of the hazard of using a
pd.Indexsubclass I suppose...It looks like pandas-dev/pandas#31511 was the cause of the issue:
A way to fix this upstream would be to make sure that
targethas the same type as the index (here it is a genericpd.Indexinstead of aCFTimeIndex), but I'm not sure how hard that would be (or if it makes sense in all cases):https://github.com/pandas-dev/pandas/blob/a2a35a86c4064d297c8b48ecfea80e9f05e27712/pandas/core/indexes/base.py#L3080
I think it's possible we could work around this in xarray. It comes down to properly recognizing what to do when you subtract a generic
pd.Indexofcftime.datetimeobjects from aCFTimeIndex. Previously this code in pandas operated strictly using NumPy arrays, so there was no casting issue when doing the subtraction.dcherian commentedon Feb 6, 2020
Thanks for narrowing it down @spencerkclark . Let's see what @TomAugspurger thinks about an xarray workaround vs a pandas fix.
TomAugspurger commentedon Feb 6, 2020
FWIW, I think @jbrockmendel is still progressing on an "extension index" interface where you could have a custom dtype / Index subclass that would be properly supported. Long-term, that's the best solution.
Short-term, I'm less sure what's best.
jbrockmendel commentedon Feb 6, 2020
any idea what
otheris here? looks like it might be a DatetimeIndexspencerkclark commentedon Feb 7, 2020
Nice -- I look forward to being able to try that out!
@jbrockmendel agreed that it's unclear -- we probably should have written the code for that method in a clearer way. I think it's mainly used for subtracting a single
datetime.timedeltaor NumPy array ofdatetime.timedeltaobjects from aCFTimeIndex. In both of those cases we would expect the result to remain aCFTimeIndex.cftime.datetimeobjects often represent dates from non-standard calendars (e.g. calendars with no leap year, or calendars where all months have 30 days), so in general they are not compatible with the dates used in a DatetimeIndex. Subtracting like-calendarcftime.datetimeobjects is fair game though, and we'd like that to produce timedeltas.keewis commentedon Feb 7, 2020
when the tests fail,
otheris apandas.Indexcontaining whatever has been used to index. The subtraction results in a normalTimedeltaIndexwhich is then passed to theCFTimeIndex:I think the issue here is that
otheris apandas.Indexinstead of aCFTimeIndex.spencerkclark commentedon Feb 7, 2020
Yes, I noted that in my original post (sorry if that wasn't clear).
keewis commentedon Feb 7, 2020
no, that's my bad, it is pretty clear but I seem to have skipped over it
spencerkclark commentedon Feb 18, 2020
Another kind of failure came up in the context of indexing a Series with a
cftime.datetimeobject:Example failure
Admittedly I think most people probably use a CFTimeIndex within xarray data structures, but it would be nice to maintain some ability to use it in pandas data structures too. This issue stems from the changes made in pandas-dev/pandas#31399. I think the problem is that
pandas.core.dtypes.common.is_scalarreturnsFalsefor acftime.datetimeobject:Could there be a simple upstream fix for this?
jbrockmendel commentedon Feb 18, 2020
Yah, pandas recently added a check for
is_scalar(key)inSeries.__getitem__to try to avoid some unnecessary lookups. That will need to be changed to accommodate unexpected scalars.xfail tests due to pydata#3751
spencerkclark commentedon Feb 28, 2020
@jbrockmendel @TomAugspurger it turns out that fixing indexing with the "nearest" method without overriding private methods of
pandas.Indexis harder than I expected within xarray alone (see #3764 (comment) for more details). Do you think an upstream fix would be acceptable here? My understanding is that the issue that prompted the change in pandas only pertained to DatetimeIndexes (or perhaps maybe also PeriodIndexes in the future); would it be possible to limit the scope of the updates in pandas-dev/pandas#31511 to just those?xfail tests due to #3751 (#3808)
jbrockmendel commentedon Feb 28, 2020
Definitely. Is it still the case that the identified problems would all be solved by having
is_scalarrecognize cftime.datetime?spencerkclark commentedon Feb 28, 2020
Thanks @jbrockmendel -- I think there are two separate issues:
__getitem__in a Series would be solved by theis_scalarfix.jbrockmendel commentedon Mar 10, 2020
@spencerkclark can you open an issue on the pandas tracker about this and ping me there; I dont want this to fall off my radar
spencerkclark commentedon Mar 11, 2020
Thanks @jbrockmendel -- I'll try to do that this weekend.
spencerkclark commentedon Mar 15, 2020
Thanks so much @jbrockmendel for looking into the
__getitem__issue upstream. That should be the last of the issues that remains from this thread. As you probably noticed, we ended up merging #3764, which fixed indexing with the "nearest" method.Once pandas-dev/pandas#32684 is merged, we should be able to un-xfail the Series
__getitem__tests on our end.jbrockmendel commentedon Mar 16, 2020
We're making progress on pandas-dev/pandas#32684, I'd also like to see if we can do an in-pandas fix to avoid the need to override more things here (i.e. #3764). Seems like that will lead to fewer headaches long-term.
Since pandas-dev/pandas#31511, the method has been updated to remove an np.asarray call, and I'm curious if that is enough to make #3764 unnecessary. The only remaining difference AFAICT is
np.absvsabs, which seems like it shouldnt be too tough to resolve.spencerkclark commentedon Mar 21, 2020
Thanks @jbrockmendel; it's great to see that pandas-dev/pandas#32684 was merged.
Regarding #3764, I gave things a try with pandas master and removing our overrides to
_get_nearest_indexerand_filter_indexer_tolerance. I got similar failures to what we were getting before.Example failure
In my testing, I can only get things to work if the argument to
abs(ornp.abs) is a NumPy array (instead of an Index). An upstream change like this would work (it still maintains the behavior desired from pandas-dev/pandas#31511), but I'm not sure how palatable it would be.jbrockmendel commentedon Mar 21, 2020
Can you open a pandas PR for the cftime-nearest-fix branch, and add a test in tests/test_downstream.py for the problematic behavior? That branch won't be merged as-is, but it will be easier to discuss options in-line.
spencerkclark commentedon Mar 22, 2020
Thanks @jbrockmendel. I didn't realize you had a few downstream tests; that's great. See pandas-dev/pandas#32905.
Fix to _get_nearest_indexer for pydata/xarray#3751 (#32905)
Backport PR pandas-dev#32905 on branch 1.0.x (Fix to _get_nearest_ind…
Backport PR #32905 on branch 1.0.x (Fix to _get_nearest_indexer for p…
pandas: Autospec creation for update from version 1.0.3 to version 1.0.4