0

From xarray's tutorial data, I want to extract a DataArray that contains number of warm days in month, defined as between 22 and 30 Celcius:

airtemps = xr.tutorial.load_dataset('air_temperature')
airtemps = airtemps.sel(time=slice('2013-01-01', '2013-12-31'))
airtemps['air'] = airtemps.air - 273.15

air_day = airtemps.resample('1D', 'time', how='mean')
# Define multiple conditions - How can this be done programatically?

I am now looking for a way to create this map below programmatically, also being able to add more conditions

meets_condition = (air_day.air > 22) & (air_day.air < 30)
warm_days = meets_condition.resample('M', dim='time', how='sum')

Conditions could be defined like so:

not_cold = ('air',  operator.ge, 22)
not_hot  = ('air',  operator.le, 30)

I can do this simply with one condition:

variable, operator_fn, value = not_cold
meets_condition = operator_fn(air_day[variable], value)
warm_but_possibly_hot_days = meets_condition.resample('M', dim='time', how='sum')

But I'm struggeling adding multiple, dynamically. I can do this

comfy_warm = [not_cold, not_hot]

all_maps = [fn(air_day[var], val) for var, fn, val in comfy_warm]
(all_maps[0] & all_maps[1]).resample('M', dim='time', how='sum')

But I'm looking to do sth. like this

np.all(all_maps).resample('M', dim='time', how='sum')

Here's a gist for convenience. As always, I am thankful in advance

2 Answers 2

1

We cannot feed np.logical_and.reduce() with DataArrays, but it works nicely with pure arrays, so that's I then feed it with

all_maps = [fn(air_day[var], val).values for var, fn, val in comfy_warm]

I then add this map as a new data variable and resample it

air_day['nice_days'] = (['time', 'lat', 'lon'], np.logical_and.reduce(all_maps))    
air_day.nice_days.resample('M', dim='time', how='sum')
Sign up to request clarification or add additional context in comments.

Comments

1

I think you want this:

xr.ufuncs.logical_and.reduce(all_maps)

It applies the and operation element-wise across all the boolean arrays of the same length, and produces one result of that same length. Of course you can use logical_or or any other suitable ufunc.

4 Comments

I already tried this, but it a) takes forever (once 2m, now 7m(!)) compared to the 18 ms when doing it the manual way and b) it returns an np.array, I'd prefer a DataArray
@TomTom101: Oh, I see--I had written np.logical_and but I see now that xarray has its own reimplementations of some of the ufuncs. I guess they're not compatible with NumPy, so I'll update my answer now to use the xarray version. Please try again and I hope you'll see good performance.
Still complains: AttributeError: '_UFuncDispatcher' object has no attribute 'reduce'
@TomTom101: Oh well, I give up. I just use Pandas and NumPy like everybody else.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.