TypeError: '_ElementwiseFunctionArray' object does not support item assignment
Nobody has claimed this yet.
- Dominant language
- Python
- Stars
- 4.2k
- Forks
- 1.4k
- Avg merge
- 2d 15h
- Merged PRs (30d)
- 14
Description
What happened:
I am attempting to mask specific time_bnds coordinate points using loc, but am receiving TypeError: '_ElementwiseFunctionArray' object does not support item assignment.
This happens with datasets that have encoded (raw) time coordinates, then decoding with xr.decode_cf() before attempting to mask the time_bnds.
What you expected to happen:
The time_bnds coordinate points selected using .loc should mask properly
Minimal Complete Verifiable Example:
MVCE 1 -- breaks with encoded time coordinates then decoded using xr.decode_cf()
import numpy as np
import xarray as xr
time_encoded = xr.DataArray(
name="time",
data=[675348.5, 675378.0, 675407.5],
dims=["time"],
attrs={
"bounds": "time_bnds",
"units": "days since 0001-01-01",
"calendar": "proleptic_gregorian",
"axis": "T",
"long_name": "time",
"standard_name": "time",
},
)
time_bnds_encoded = xr.DataArray(
name="time_bnds",
data=[[675333.0, 675364.0], [675364.0, 675392.0], [675392.0, 675423.0]],
dims=["time", "bnds"],
)
ds = xr.Dataset(
coords={"time": time_encoded}, data_vars={"time_bnds": time_bnds_encoded}
)
ds = xr.decode_cf(ds, decode_times=True)
ds["time_bnds"].loc[dict(time="1850-01")] = np.nan
MVCE 2 -- works fine with decoded time coordinates
import cftime
import numpy as np
import xarray as xr
time_decoded = xr.DataArray(
name="time",
data=np.array(
[
cftime.DatetimeProlepticGregorian(
1850, 1, 16, 12, 0, 0, 0, has_year_zero=True
),
cftime.DatetimeProlepticGregorian(
1850, 2, 15, 0, 0, 0, 0, has_year_zero=True
),
cftime.DatetimeProlepticGregorian(
1850, 3, 16, 12, 0, 0, 0, has_year_zero=True
),
],
dtype="object",
),
dims=["time"],
attrs={
"bounds": "time_bnds",
"axis": "T",
"long_name": "time",
"standard_name": "time",
},
)
time_decoded.encoding = {
"units": "days since 0001-01-01",
"calendar": "proleptic_gregorian",
}
time_bnds_decoded = xr.DataArray(
dims=["time", "bnds"],
data=[
[np.nan, np.nan],
[
cftime.DatetimeProlepticGregorian(
1850, 2, 1, 0, 0, 0, 0, has_year_zero=True
),
cftime.DatetimeProlepticGregorian(
1850, 3, 1, 0, 0, 0, 0, has_year_zero=True
),
],
[
cftime.DatetimeProlepticGregorian(
1850, 3, 1, 0, 0, 0, 0, has_year_zero=True
),
cftime.DatetimeProlepticGregorian(
1850, 4, 1, 0, 0, 0, 0, has_year_zero=True
),
],
],
)
ds = xr.Dataset(
coords={"time": time_decoded}, data_vars={"time_bnds": time_bnds_decoded}
)
ds["time_bnds"].loc[dict(time="1850-01")] = np.nan
Anything else we need to know?:
The workaround is to perform .load() after xr.decode_cf()
import numpy as np
import xarray as xr
time_encoded = xr.DataArray(
name="time",
data=[675348.5, 675378.0, 675407.5],
dims=["time"],
attrs={
"bounds": "time_bnds",
"units": "days since 0001-01-01",
"calendar": "proleptic_gregorian",
"axis": "T",
"long_name": "time",
"standard_name": "time",
},
)
time_bnds_encoded = xr.DataArray(
name="time_bnds",
data=[[675333.0, 675364.0], [675364.0, 675392.0], [675392.0, 675423.0]],
dims=["time", "bnds"],
)
ds = xr.Dataset(
coords={"time": time_encoded}, data_vars={"time_bnds": time_bnds_encoded}
)
ds = xr.decode_cf(ds, decode_times=True)
ds.load()
ds["time_bnds"].loc[dict(time="1850-01")] = np.nan
Log Output
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
File /Users/vo13/repositories/xcdat/qa/xr_6015.py:27
[23](https://file+.vscode-resource.vscode-cdn.net/Users/vo13/repositories/xcdat/qa/xr_6015.py:23) ds = xr.Dataset(
[24](https://file+.vscode-resource.vscode-cdn.net/Users/vo13/repositories/xcdat/qa/xr_6015.py:24) coords={"time": time_encoded}, data_vars={"time_bnds": time_bnds_encoded}
[25](https://file+.vscode-resource.vscode-cdn.net/Users/vo13/repositories/xcdat/qa/xr_6015.py:25) )
[26](https://file+.vscode-resource.vscode-cdn.net/Users/vo13/repositories/xcdat/qa/xr_6015.py:26) ds = xr.decode_cf(ds, decode_times=True)
---> [27](https://file+.vscode-resource.vscode-cdn.net/Users/vo13/repositories/xcdat/qa/xr_6015.py:27) ds["time_bnds"].loc[dict(time="1850-01")] = np.nan
File /opt/miniconda3/envs/xcdat_dev/lib/python3.11/site-packages/xarray/core/dataarray.py:246, in _LocIndexer.__setitem__(self, key, value)
[243](https://file+.vscode-resource.vscode-cdn.net/opt/miniconda3/envs/xcdat_dev/lib/python3.11/site-packages/xarray/core/dataarray.py:243) key = dict(zip(self.data_array.dims, labels))
[245](https://file+.vscode-resource.vscode-cdn.net/opt/miniconda3/envs/xcdat_dev/lib/python3.11/site-packages/xarray/core/dataarray.py:245) dim_indexers = map_index_queries(self.data_array, key).dim_indexers
--> [246](https://file+.vscode-resource.vscode-cdn.net/opt/miniconda3/envs/xcdat_dev/lib/python3.11/site-packages/xarray/core/dataarray.py:246) self.data_array[dim_indexers] = value
File /opt/miniconda3/envs/xcdat_dev/lib/python3.11/site-packages/xarray/core/dataarray.py:892, in DataArray.__setitem__(self, key, value)
[887](https://file+.vscode-resource.vscode-cdn.net/opt/miniconda3/envs/xcdat_dev/lib/python3.11/site-packages/xarray/core/dataarray.py:887) # DataArray key -> Variable key
[888](https://file+.vscode-resource.vscode-cdn.net/opt/miniconda3/envs/xcdat_dev/lib/python3.11/site-packages/xarray/core/dataarray.py:888) key = {
[889](https://file+.vscode-resource.vscode-cdn.net/opt/miniconda3/envs/xcdat_dev/lib/python3.11/site-packages/xarray/core/dataarray.py:889) k: v.variable if isinstance(v, DataArray) else v
[890](https://file+.vscode-resource.vscode-cdn.net/opt/miniconda3/envs/xcdat_dev/lib/python3.11/site-packages/xarray/core/dataarray.py:890) for k, v in self._item_key_to_dict(key).items()
[891](https://file+.vscode-resource.vscode-cdn.net/opt/miniconda3/envs/xcdat_dev/lib/python3.11/site-packages/xarray/core/dataarray.py:891) }
--> [892](https://file+.vscode-resource.vscode-cdn.net/opt/miniconda3/envs/xcdat_dev/lib/python3.11/site-packages/xarray/core/dataarray.py:892) self.variable[key] = value
File /opt/miniconda3/envs/xcdat_dev/lib/python3.11/site-packages/xarray/core/variable.py:866, in Variable.__setitem__(self, key, value)
[863](https://file+.vscode-resource.vscode-cdn.net/opt/miniconda3/envs/xcdat_dev/lib/python3.11/site-packages/xarray/core/variable.py:863) value = np.moveaxis(value, new_order, range(len(new_order)))
[865](https://file+.vscode-resource.vscode-cdn.net/opt/miniconda3/envs/xcdat_dev/lib/python3.11/site-packages/xarray/core/variable.py:865) indexable = as_indexable(self._data)
--> [866](https://file+.vscode-resource.vscode-cdn.net/opt/miniconda3/envs/xcdat_dev/lib/python3.11/site-packages/xarray/core/variable.py:866) indexing.set_with_indexer(indexable, index_tuple, value)
File /opt/miniconda3/envs/xcdat_dev/lib/python3.11/site-packages/xarray/core/indexing.py:1012, in set_with_indexer(indexable, indexer, value)
[1010](https://file+.vscode-resource.vscode-cdn.net/opt/miniconda3/envs/xcdat_dev/lib/python3.11/site-packages/xarray/core/indexing.py:1010) indexable.oindex[indexer] = value
[1011](https://file+.vscode-resource.vscode-cdn.net/opt/miniconda3/envs/xcdat_dev/lib/python3.11/site-packages/xarray/core/indexing.py:1011) else:
-> [1012](https://file+.vscode-resource.vscode-cdn.net/opt/miniconda3/envs/xcdat_dev/lib/python3.11/site-packages/xarray/core/indexing.py:1012) indexable[indexer] = value
File /opt/miniconda3/envs/xcdat_dev/lib/python3.11/site-packages/xarray/core/indexing.py:660, in LazilyIndexedArray.__setitem__(self, key, value)
[658](https://file+.vscode-resource.vscode-cdn.net/opt/miniconda3/envs/xcdat_dev/lib/python3.11/site-packages/xarray/core/indexing.py:658) self._check_and_raise_if_non_basic_indexer(key)
[659](https://file+.vscode-resource.vscode-cdn.net/opt/miniconda3/envs/xcdat_dev/lib/python3.11/site-packages/xarray/core/indexing.py:659) full_key = self._updated_key(key)
--> [660](https://file+.vscode-resource.vscode-cdn.net/opt/miniconda3/envs/xcdat_dev/lib/python3.11/site-packages/xarray/core/indexing.py:660) self.array[full_key] = value
TypeError: '_ElementwiseFunctionArray' object does not support item assignment
Environment:
Output of xr.show_versions()
INSTALLED VERSIONS
commit: None
python: 3.11.9 | packaged by conda-forge | (main, Apr 19 2024, 18:34:54) [Clang 16.0.6 ]
python-bits: 64
OS: Darwin
OS-release: 22.6.0
machine: arm64
processor: arm
byteorder: little
LC_ALL: None
LANG: None
LOCALE: (None, 'UTF-8')
libhdf5: 1.14.3
libnetcdf: 4.9.2
xarray: 2024.3.0
pandas: 2.2.2
numpy: 1.26.4
scipy: 1.13.0
netCDF4: 1.6.5
pydap: None
h5netcdf: None
h5py: None
Nio: None
zarr: None
cftime: 1.6.3
nc_time_axis: 1.4.1
iris: None
bottleneck: None
dask: 2024.4.2
distributed: 2024.4.2
matplotlib: 3.8.4
cartopy: None
seaborn: None
numbagg: None
fsspec: 2024.3.1
cupy: None
pint: None
sparse: 0.15.1
flox: None
numpy_groupies: None
setuptools: 69.5.1
pip: 24.0
conda: None
pytest: 8.2.0
mypy: 1.4.0
IPython: 8.22.2
sphinx: 7.3.7
/opt/miniconda3/envs/xcdat_dev/lib/python3.11/site-packages/_distutils_hack/init.py:26: UserWarning: Setuptools is replacing distutils.
warnings.warn("Setuptools is replacing distutils.")
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by reproducing the two minimal examples around xr.decode_cf(), DataArray.loc assignment, and the traceback through xarray's indexing path. Confirm that the encoded-time case fails before load() and the decoded case succeeds; done means the encoded-time assignment works without requiring load(), with a regression test for the reported example.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- numpy, python
- Domain
- data
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Clearly specified
- Newbie friendliness
- 48/100