Как объединить данные из нескольких файлов NetCDF с помощью xarray в Python?

#python #concatenation #netcdf #python-xarray

#python #конкатенация #netcdf #python-xarray

Вопрос:

Я пытаюсь открыть несколько файлов NetCDF с помощью xarray в Python. Файлы содержат данные одинаковой формы, и я хочу объединить их, создав новое измерение.

Я попытался использовать аргумент concat_dim для xarray.open_mfdataset(), но он работает не так, как ожидалось. Ниже приведен пример, который открывает два файла с данными о температуре для 124 раз, 241 широты и 480 долгот:

 DS = xr.open_mfdataset( 'eraINTERIM_t2m_*.nc', concat_dim='cases' )
da_t2m = DS.t2m

print( da_t2m )
  

С помощью этого кода я ожидаю, что результирующий массив данных будет иметь форму, подобную (случаи: 2, время: 124, широта: 241, долгота: 480). Однако его форма была (случаев: 2, время: 248, широта: 241, долгота: 480).
Это создает новое измерение, но также суммирует крайнее левое измерение: измерение ‘time’ двух наборов данных.
Мне было интересно, является ли это ошибкой из ‘xarray.open_mfdateset’ или это ожидаемое поведение, потому что измерение ‘time’ не ограничено для обоих наборов данных.

Есть ли способ объединить данные из этих файлов напрямую с помощью xarray и получить вышеуказанный ожидаемый результат?

Спасибо.

Матеус

Комментарии:

1. Совпадают ли временные измерения (т. Е. Оба файла содержат данные за один и тот же временной диапазон)?

2. Измерение времени имеет одинаковую длину в обоих файлах, 124 временных индекса. Однако они не охватывают один и тот же период времени.

3. Xarray пытается выровнять ваши данные по существующему временному измерению. Какой бы вы хотели, чтобы ваша временная координата была после того, как xarray объединит отдельные наборы данных?

4. Если вы думаете о разных случаях или событиях с разными периодами времени (но одинаковой длины), у вас может получиться большой массив с данными для разных событий, каждое из которых имеет свою продолжительность. Таким образом, результирующий массив будет иметь дополнительное измерение: события.

5. @Mateus Вы могли бы попробовать переименовать / скопировать / удалить измерение времени с новым новым измерением, которое равно для каждого файла (всего 0,1, …, 123). Это может быть сделано с помощью preprocess ключевого аргумента open_mfdataset. Я делаю что-то подобное, но у меня нет кода под рукой atm.

Ответ №1:

Исходя из моего комментария, я бы попробовал это:

 def preproc(ds):
    ds = ds.assign({'stime': (['time'], ds.time)}).drop('time').rename({'time': 'ntime'})
    # we might need to tweak this a bit further, depending on the actual data layout
    return ds

DS = xr.open_mfdataset( 'eraINTERIM_t2m_*.nc', concat_dim='cases', preprocess=preproc)
  

Хорошая вещь здесь в том, что вы сохраняете исходную временную координату в stime при переименовании исходного измерения ( time -> ntime ).

Если все работает хорошо, вы должны получить результирующие размеры в виде ( cases , ntime , latitude , longitude ).

Отказ от ответственности: я делаю подобное в цикле с окончательным объединением (которое работает очень хорошо), но не тестировал preprocess -подход.

Комментарии:

1. Спасибо @kmuehlbauer! Ваш код работает очень хорошо, включая сохранение дат в stime переменной.

2. Слава всем тем людям, которые отлично работают под эгидой PyData. Эти пакеты (например, pandas, xarray и т.д.) Действительно улучшили мои рабочие процессы.

Ответ №2:

Спасибо @AdrianTompkins и @jhamman. После ваших комментариев я понимаю, что из-за разных периодов времени я действительно не могу получить то, что хочу, с помощью xarray.

Моя основная цель создания такого массива — получить в одном N-D массиве все данные для разных событий с одинаковой продолжительностью времени. Таким образом, я могу легко получить, например, составные поля всех событий для каждого времени (час, день и т.д.).

Я пытаюсь сделать то же самое, что и с NCL. Смотрите ниже код для NCL, который работает, как ожидалось (для меня), для одних и тех же данных:

 f = addfiles( (/"eraINTERIM_t2m_201812.nc", "eraINTERIM_t2m_201901.nc"/), "r" )
ListSetType( f, "join" )
temp = f[:]->t2m
printVarSummary( temp )
  

Конечным результатом является массив с 4 измерениями, причем новому автоматически присваивается имя ncl_join.

Однако NCL не учитывает ось времени, соединяет массивы и присваивает результирующей оси времени координаты первого файла. Таким образом, ось времени становится бесполезной.

Однако, как хорошо сказано для @AdrianTompkins, периоды времени разные, и xarray не может объединять данные подобным образом. Итак, чтобы создать такой массив в Python с помощью xarray, я думаю, единственный способ — удалить временную координату из массивов. Таким образом, измерение времени будет иметь только целочисленные индексы.

Массив, предоставленный xarray, работает так, как @AdrianThompkins сказал в своем небольшом примере. Поскольку он сохраняет временные координаты для всех объединенных данных, я думаю, что решение xarray является правильным по сравнению с NCL. Но теперь я думаю, что вычисление композитов (получение того же примера, приведенного выше) не было бы выполнено так просто, как кажется с NCL.

В небольшом тесте я печатаю два значения из объединенного массива с помощью xarray с

 print( da_t2m[ 0, 0, 0, 0 ].values )
print( da_t2m[ 1, 0, 0, 0 ].values )
  

Что приводит к

 252.11412
nan
  

Во втором случае данные в первый раз отсутствуют, как и ожидалось.

ОБНОВЛЕНИЕ: все ответы помогают мне лучше понять эту проблему, поэтому мне пришлось добавить обновление здесь, чтобы также поблагодарить @kmuehlbauer за его ответ, указав, что его код выдает ожидаемый массив.

Еще раз, спасибо всем за помощь!

Матеус

Комментарии:

1. Понятно, почему вы не читаете каждый файл отдельно в цикле и не помещаете данные в массив 4D numpy в этом случае, вместо того, чтобы использовать функцию xarray concat?

2. Я просто пытаюсь избежать циклов, используя эту возможность xarray. Но, я думаю, что я не смогу. Спасибо.

Ответ №3:

Результат имеет смысл, если времена разные.

Чтобы упростить это, забудьте на мгновение о широте и представьте, что у вас есть два файла, которые являются просто данными с интервалом в 2 раза. Первый содержит данные с временными интервалами 1,2, а второй файл с временными интервалами 3 и 4. Вы не можете создать объединенный набор данных с временным измерением, которое охватывает только 2 временных интервала; переменная измерения времени должна иметь времена 1,2,3,4. Итак, если вы говорите, что хотите новое измерение «cases», то данные затем объединяются в виде 2d-массива и будут выглядеть следующим образом:

 times: 1,2,3,4

cases: 1,2

data: 
               time
          1    2    3    4
cases 1:  x1   x2 
      2:            x3   x4
  

Подумайте о файле netcdf, который был бы эквивалентен, измерение времени должно охватывать диапазон значений, присутствующих в обоих файлах. Единственный способ, которым вы могли бы объединить два файла и получить (случаи: 2, время: 124, широта: 241, долгота: 480), — это если оба файла имеют одинаковые значения времени, широты И долготы, т. Е. Указывают на точно такую же область в пространстве время-широта-долгота.

ps: Несколько не по теме вопроса, но если вы только начинаете новый анализ, почему бы вместо этого не переключиться на новое поколение, с более высоким разрешением ERA-5 reanalysis, который теперь доступен еще с 1979 года (и в конечном итоге будет расширен), вы можете загрузить его прямо на свой рабочий стол с помощью скриптов python api отсюда:

https://cds.climate.copernicus.eu/cdsapp #!/search?type=dataset