html_url,issue_url,id,node_id,user,created_at,updated_at,author_association,body,reactions,performed_via_github_app,issue https://github.com/pydata/xarray/issues/7005#issuecomment-1240646680,https://api.github.com/repos/pydata/xarray/issues/7005,1240646680,IC_kwDOAMm_X85J8sQY,1797906,2022-09-08T12:24:41Z,2022-09-08T12:24:41Z,NONE,"Hi @benbovy, Thanks for the detailed response. Yeah, that it was only raising for the second multi indexing map, does seem like a bug in that case, I'll leave the ticket open to track that. I didn't stumble on the `set_levels` function while skimming though the docs, thanks. I've updated my function to make use of that. I'm hoping things should be safe with this, and I'm correctly replacing things in the correct order. For anyone else who's looking to do the same, or for anyone to tell me what I'm doing is not safe, or there's a simpler way, here's the updated function: ```python import numpy as np import pandas as pd import xarray as xr def map_coords(ds, *, name, mapping): """""" Takes a xarray dataset's coordinate values and updates them with the given the provided mapping. In-place. Can handle both regular indices and multi-level indices. ds: An xr.Datset name: name of the coordinate to update mapping: dictionary, key of old value, value of new value. """""" # all attrs seem to get dropped on coords even if only # one is altered. Hold on to them and reapply after coord_attrs = {c: ds[c].attrs for c in ds.coords} if ds.indexes.is_multi(name): target = name parent = ds.indexes[target].name if target == parent: valid_targets = ds.indexes[parent].names raise ValueError( f""Can only map levels of a MultiIndex, not the MultiIndex "" f""itself. Target one of {valid_targets}"", ) multi_index = ds.indexes[parent] level_values = dict(zip(multi_index.names, multi_index.levels)) new_values = [mapping[v] for v in level_values[name]] ds.coords[parent] = multi_index.set_levels(new_values, level=target) else: old_values = ds.coords[name].values new_values = [mapping[v] for v in old_values] ds[name] = new_values # reapply attrs for coord, attrs in coord_attrs.items(): ds[coord].attrs = attrs midx = pd.MultiIndex.from_product([list(""abc""), [0, 1]], names=(""x_one"", ""x_two"")) midy = pd.MultiIndex.from_product([list(""abc""), [0, 1]], names=(""y_one"", ""y_two"")) mda = xr.DataArray(np.random.rand(6, 6, 3), [(""x"", midx), (""y"", midy), (""z"", range(3))]) map_coords(mda, name=""z"", mapping={0: ""zero"", 1: ""one"", 2: ""two""}) map_coords(mda, name=""x_one"", mapping={""a"": ""aa"", ""b"": ""bb"", ""c"": ""cc""}) map_coords(mda, name=""y_one"", mapping={""a"": ""aa"", ""b"": ""bb"", ""c"": ""cc""}) print(mda) ```","{""total_count"": 0, ""+1"": 0, ""-1"": 0, ""laugh"": 0, ""hooray"": 0, ""confused"": 0, ""heart"": 0, ""rocket"": 0, ""eyes"": 0}",,1364911775