Вычислить массив данных xarray по координатным меткам

У меня есть DataArray с двумя переменными (метеорологические данные) с течением времени, координаты y, x. Координаты x и y находятся в системе координат проекции (EPSG: 3035) и выровнены так, чтобы каждая ячейка почти точно покрывала стандартную ячейку 1 км координатной сетки LAEA

Я хочу подготовить данные для дальнейшего использования в таблицах Pandas и / или баз данных, поэтому я хочу добавить номер / метку ячейки сетки LAEA, которая может быть вычислена из x и y напрямую с помощью следующей (псевдо) функции

def func(cell):
    return r'1km{}{}'.format(int(cell['y']/1000), int(cell['x']/1000))      # e.g. 1kmN2782E4850

Но, насколько я понимаю, похоже, нет возможности применить эту функцию к DataArray или DataSet таким образом, чтобы у меня был доступ к этим координатным переменным (по крайней мере, .apply_ufunc() на самом деле не работал для меня.

Позже я смогу вычислить это на Pandas, но некоторые из моих наборов данных содержат от 60 до 120 миллионов. У Cells / Rows / datasets и pandas (даже с Numba), похоже, проблемы с этим количеством. На xarray я могу обработать это на 32 ядрах через Dask.

Буду признателен за любой совет, как заставить это работать.

РЕДАКТИРОВАТЬ: Еще немного информации о данных, с которыми я работаю:

Это самый большой с 500 миллионами ячеек, но я могу уменьшить его до разрешения квадратного километра, которое в итоге составляет около 160 миллионов. клетки

Xarray vci с ежемесячными индексами состояния растительности за несколько десятилетий

Если набор данных достаточно мал, я могу экспортировать его как фрейм данных pandas и вычислить там, но это медленно и не очень надежно, поскольку ядро ​​довольно часто дает сбой.

та же калька в пандах


person Jürgen Zornig    schedule 26.03.2021    source источник
comment
не могли бы вы предоставить несколько примеров данных или показать, как выглядит ваш массив данных?   -  person Val    schedule 29.03.2021


Ответы (2)


Вот как вы можете применить свою функцию:

import xarray as xr

# ufunc
def func(x, y):
    #print(y)
     return r'1km{}{}'.format(int(y), int(x))

# test data
ds = xr.tutorial.load_dataset("rasm")

xr.apply_ufunc(
    func, 
    ds.x,
    ds.y,
    vectorize=True,
)

Обратите внимание, что вам не нужно указывать input_core_dims в вашем случае.

Кроме того, поскольку ваша функция не векторизована, вам необходимо установить vectorized=True:

vectorize: bool, optional Если True, то предположим, что func принимает в качестве входных данных только массивы, определенные по размерам ядра, и автоматически векторизует их с помощью: py: func: numpy.vectorize. Эта опция существует для удобства, но почти всегда работает медленнее, чем предоставление предварительно векторизованной функции. Для использования этой опции требуется NumPy версии 1.12 или новее.

Использование vectorized может быть не самым эффективным вариантом, поскольку по сути это просто цикл, но если у вас есть данные в кусках и вы используете dask, этого может быть достаточно.

Если нет, вы можете изучить создание векторизованной функции, например, с помощью numba, которая наверняка ускорит процесс.

Дополнительную информацию можно найти в руководстве по xarray на применение ufuncs

person Val    schedule 29.03.2021
comment
Спасибо, именно то, что я искал. Работает молниеносно. DataSet теперь становится настолько большим, что я даже не могу переопределить его как pd DataFrame, но это уже другая история, и я думаю, что я просто буду придерживаться xray как можно дольше. P.S: возможно, отредактируйте свой ответ для других, поскольку df_vci - это фрейм данных Pandas в моем примере, тогда как соответствующий Xray просто идентифицируется как vci - person Jürgen Zornig; 29.03.2021

Вы можете использовать apply_ufunc невекторизованным способом:

def func(x, y):
    return f'1km{int(y/1000)}{int(x/1000)}'  # e.g. 1kmN2782E4850

xr.apply_ufunc(
    func, # first the function
    x.x,  # now arguments in the order expected by 'func'
    x.y
    )
person iacob    schedule 29.03.2021
comment
что приводит к TypeError: only size-1 arrays can be converted to Python scalars ... я должен сначала сделать что-то вроде reset_index()? Есть ли возможность напрямую получить доступ к координатам без предварительного сброса индекса? - person Jürgen Zornig; 29.03.2021
comment
@ JürgenZornig, не видя, как выглядит ваш xarray, я не могу сказать вам, как исправить эту ошибку - похоже, он применяет функцию ко всей серии (столбцу), а не к каждому отдельному значению. - person iacob; 29.03.2021
comment
Я добавил несколько скриншотов выше - person Jürgen Zornig; 29.03.2021
comment
Я очень ценю ваши усилия по предоставлению полезных советов, к сожалению, это не сработало, и я не смог разобраться самостоятельно, тогда как ответ @Val предоставил пример рабочего кода, а также объяснение и полезные ссылки. Я как можно больше поддерживаю ваши ответы, большое спасибо за вашу помощь - person Jürgen Zornig; 29.03.2021
comment
@ jürgenzornig не беспокойтесь - да, я забыл добавить vectorised = True arg. - person iacob; 29.03.2021