Нарезка набора данных xarray с координатно-зависимой переменной - PullRequest
0 голосов
/ 18 июня 2020

Я построил набор данных xarray в python3 с координатами (time, levels), чтобы идентифицировать все основания облаков и вершины облаков в течение одного дня наблюдений. Переменная levels - это размер основания / вершины облаков, которые могут быть идентифицированы в данный момент времени. Он хранит значения высоты основания / вершины облаков для каждого времени.

Теперь я хочу выбрать все основания и вершины облаков, которые расположены в заданном диапазоне высот, которые меняются во времени. Диапазон высоты определяется массивами bottom_mod и top_mod. Эти массивы имеют размер time и содержат края диапазона выбранных высот.

Набор данных xarray: cloudStandard_mod_reshaped:

Dimensions:     (levels: 8, time: 9600)
Coordinates:
  * levels      (levels) int64 0 1 2 3 4 5 6 7
  * time        (time) datetime64[ns] 2013-04-14 ... 2013-04-14T23:59:51
Data variables:
    cloudTop    (time, levels) float64 nan nan nan nan nan ... nan nan nan nan
    cloudThick  (time, levels) float64 nan nan nan nan nan ... nan nan nan nan
    cloudBase   (time, levels) float64 nan nan nan nan nan ... nan nan nan nan

Я попытался выбрать высоты в диапазоне, определяемом верхним и нижним массивами следующим образом:

PBLclouds = cloudStandard_mod_reshaped.sel(levels=slice(bottom_mod[:], top_mod[:]))

, но эта инструкция принимает только скалярные значения для команды среза.

Вы знаете, как срезать со значениями, которые являются зависит от координат?

1 Ответ

0 голосов
/ 01 июля 2020

Вы можете использовать метод .where().

Строка с решением находится под 2.

1. Сначала создайте данные, подобные вашим:

Набор данных:

nlevels, ntime = 8, 50

ds = xr.Dataset(
    coords=dict(levels=np.arange(nlevels), time=np.arange(ntime),),
    data_vars=dict(
        cloudTop=(("levels", "time"), np.random.randn(nlevels, ntime)),
        cloudThick=(("levels", "time"), np.random.randn(nlevels, ntime)),
        cloudBase=(("levels", "time"), np.random.randn(nlevels, ntime)),
    ),
)

вывод print(ds):

<xarray.Dataset>
Dimensions:     (levels: 8, time: 50)
Coordinates:
  * levels      (levels) int64 0 1 2 3 4 5 6 7
  * time        (time) int64 0 1 2 3 4 5 6 7 8 9 ... 41 42 43 44 45 46 47 48 49
Data variables:
    cloudTop    (levels, time) float64 0.08375 0.04721 0.9379 ... 0.04877 2.339
    cloudThick  (levels, time) float64 -0.6441 -0.8338 -1.586 ... -1.026 -0.5652
    cloudBase   (levels, time) float64 -0.05004 -0.1729 0.7154 ... 0.06507 1.601

Для верхнего и нижнего уровней , Я сделаю нижний уровень случайным и просто добавлю смещение для построения верхнего уровня.

offset = 3

bot_mod = xr.DataArray(
    dims=("time"),
    coords=dict(time=np.arange(ntime)),
    data=np.random.randint(0, nlevels - offset, ntime),
    name="bot_mod",
)

top_mod = (bot_mod + offset).rename("top_mod")

вывод print(bot_mod):

<xarray.DataArray 'bot_mod' (time: 50)>
array([0, 1, 2, 2, 3, 1, 2, 1, 0, 2, 1, 3, 2, 0, 2, 4, 3, 3, 2, 1, 2, 0,
       2, 2, 0, 1, 1, 4, 1, 3, 0, 4, 0, 4, 4, 0, 4, 4, 1, 0, 3, 4, 4, 3,
       3, 0, 1, 2, 4, 0])

2. Затем выберите диапазон уровней облаков:

используйте метод .where() для выбора переменных набора данных, которые находятся между нижним и верхним уровнями:

ds_clouds = ds.where((ds.levels > bot_mod) & (ds.levels < top_mod))

вывод print(ds_clouds):

<xarray.Dataset>
Dimensions:     (levels: 8, time: 50)
Coordinates:
  * levels      (levels) int64 0 1 2 3 4 5 6 7
  * time        (time) int64 0 1 2 3 4 5 6 7 8 9 ... 41 42 43 44 45 46 47 48 49
Data variables:
    cloudTop    (levels, time) float64 nan nan nan nan nan ... nan nan nan nan
    cloudThick  (levels, time) float64 nan nan nan nan nan ... nan nan nan nan
    cloudBase   (levels, time) float64 nan nan nan nan nan ... nan nan nan nan

Он помещает nan там, где условие не выполняется, вы можете использовать метод .dropna(), чтобы избавиться из них.

3. Проверка на успех:

График cloudBase переменная набора данных до и после обработки:

fig, axes = plt.subplots(ncols=2)

ds.cloudBase.plot.imshow(ax=axes[0])
ds_clouds.cloudBase.plot.imshow(ax=axes[1])

plt.show()

Мне еще не разрешено вставлять изображения, так что это ссылка:

Исходные данные по сравнению с выбранными

...