1

I've been trying to replace the value of a cell (meaning, a point with an specific latitude and longitude) in a xarray dataset. The coordinares of my Dataset are lon, lat and time. I want to replace the value of certain lat and lon with the mean of the adjacent cells across time.

So far I've managed to replace it with an scalar (e.g. ds.loc[{'lon': long, 'lat': lat}]['qtot'] = 1, but when I try to replace it with an array or dataarray it seems ok but it does not update the value in the original dataset. I've tried the following expressions:

ds.loc[{'lon': lon, 'lat': lat}]['qtot'] = ds.loc[{'lon': slice(lon-0.5, lon+0.5), 'lat': slice(lat+0.5, lat-0.5)}]['qtot'].mean(['lat', 'lon'])

ds.loc[{'lon': lon, 'lat': lat}]['qtot'].values = ds.loc[{'lon': slice(lon-0.5, lon+0.5), 'lat': slice(lat+0.5, lat-0.5)}]['qtot'].mean(['lat', 'lon']).values

Any ideas would be much appreciated.

Michael Delgado
  • 13,789
  • 3
  • 29
  • 54
  • `ds.loc[{'lat': slice(y1, y2), 'lon': slice(x1, x2)}]['qtot'] = 1` doesn't work for me, whereas with `ds['qtot'].loc[{'lat': slice(y1, y2), 'lon': slice(x1, x2)}] = 1` (accessing the variable prior to slicing with `.loc`), the assignment works fine. The same is true with assigning arrays rather than scalars. Does that address the issue for you? – Michael Delgado Oct 11 '22 at 22:25

1 Answers1

1

In xarray, you can use .loc[] to assign values to DataArrays or Datasets:

# all of these work
ds.loc[{'lon': lon, 'lat': lat}] = 1
ds.loc[{'lon': lon, 'lat': lat}] = ds.loc[{'lon': lon, 'lat': lat}].mean()
ds['qstat'].loc[{'lon': lon, 'lat': lat}] = 1
ds['qstat'].loc[{'lon': lon, 'lat': lat}] = ds['qstat'].loc[{'lon': lon, 'lat': lat}].mean()

However, using .loc[] to get a view into a subset a Dataset, then referencing a variable from the view, then assigning to that does seem to break xarray's assignment handling:

# both of these have no effect
ds.loc[{'lon': lon, 'lat': lat}]['qstat'] = 1
ds.loc[{'lon': lon, 'lat': lat}]['qstat'] = ds.loc[{'lon': lon, 'lat': lat}]['qstat'].mean()

This could possibly be a bug, but it's not a pattern I've seen used often, and the more standard way of referencing an entire variable prior to slicing & assignment does work.

This seems like it could be analagous to the pandas SettingWithCopyWarning case, where a chained assignment along the lines of df.loc[slicer][colname] = 1 does not modify df.

Michael Delgado
  • 13,789
  • 3
  • 29
  • 54
  • thanks Michael! I tried to use ```ds['qstat'].loc[{'lon': lon, 'lat': lat}] = ds['qstat'].loc[{'lon': lon, 'lat': lat}].mean()``` to achieve what I wanted: ```ds['qstat'].loc[{'lon': lon, 'lat': lat}] = ds['qstat'].loc[{'lon': slice(lon+1, lon-1), 'lat': slice(lat+1, lat-1)}].mean(['lon', 'lat'])´´´, but it does not work. I understand that maybe this action is not commonly used, but what is strange is that Xarray does not print any warning. – Ruben Calvo Oct 12 '22 at 16:48
  • update: this formulation works! ```ds['qstat'].loc[{'lon': lon, 'lat': lat}] = ds['qstat'].loc[{'lon': slice(lon+1, lon-1), 'lat': slice(lat+1, lat-1)}].mean(['lon', 'lat'])´´´ Thanks Michael! – Ruben Calvo Oct 12 '22 at 16:54
  • huh - just FYI the order of your arguments to `slice` does matter. If your coordinate is in descending order (this occurs often for lat, but not lon in my experience) then you'll need to use `slice(lat + 1, lat - 1)` but `slice(lon - 1, lon + 1)` – Michael Delgado Oct 12 '22 at 16:58
  • and re: printing warnings - there's not really a way for xarray to know that you're doing this without building a whole infrastructure for determining whether you're assigning to a veiw or a whole array, and as far as I understand, this wouldn't work at all for some backends. the problem is that you are making a valid assignment, but you're doing it to a temporary object. – Michael Delgado Oct 12 '22 at 17:02