2016-09-17 2 views
0

У меня есть файл netCDF с 4 размерами. Я хочу извлечь срез из файла netCDF, указав имя одного из размеровИзвлечение среза переменной netcdf4 по размеру имени

Я знаю, как это сделать по положению. Например.

from netCDF4 import Dataset 
hndl_nc = Dataset(path_to_nc) 

# Access by slice 
hndl_nc.variables['name_variable'][:,5,:,:] 

Учитывая, что я знаю имена размеров, скажем A, B, C, D. Как получить доступ по размерному имени вместо позиции?

ответ

1

Вы можете использовать функции индексирования xarray для доступа к данным netcdf по размерному имени.

import xarray as xr 
ds = xr.open_dataset('./foo.nc') 
var = ds['name_variable'] 
# Slice var by Dimension "A" between values 0 and 5 
var_slice = var.sel(A=slice(0,5)) 
1

кажется самым близким решением тока

np.take(nc4_variable[:],dim_ids,axis=dim) 

или

nc4_variable[:].take(dim_ids,axis=dim) 

где dim_ids является список или кортеж из ваших ломтиков, и dim размерность, по которой вы хотите кусочек. К сожалению, это, кажется, сначала загружает весь набор данных, и, похоже, нет такого пути; [:] необходим. Пренебрежение им в первом методе загружает данные без корректировок из параметров add_offset, _FillValue и т. Д .; пренебрегая им во втором методе, получается ошибка.

Тестирование с помощью %timeit в Ipython подтверждает основные различия между нормальным разрезом и методом np.take.

Надеюсь, что кто-то придумает более полный ответ на это; будет очень полезна для различных наборов данных.

0

Итак, я мог бы придумать что-то, что можно квалифицировать как «решение».

Нулевые массивы, очевидно, могут быть проиндексированы одним и тем же списком итераций, например.

a = np.reshape(range(0,16),(4,4),order='F') 
a = a[ [[0,1], [1]] ] 

возвращается a равна array([4,5]). Другим примером может быть [[range(3),[1 2],3]]. Эти одиночные списки разворачиваются в порядке *subscripts, как если бы вы прямо запросили a[[0,1],1] вместо a[ [[0,1],1] ].

Итак, если вы можете запросить позицию и длину каждого измерения в переменной netCDF (довольно легко с nc_fid[var].dimension и nc_fid[var].shape), вы можете просто переставить список в соответствии с расположением каждого измерения. Например, если у вас есть данные о время формы Лон на латах, и вы хотите всех долгот, всех широты и временный индекс t=5, вы можете использовать что-то вроде

order_want = ['lon', 'lat', 'time'] # must figure out dimension names a priori 
nlon = nc_fid[var].shape[nc_fid[var].dimensions.index('lon')] 
nlat = nc_fid[var].shape[nc_fid[var].dimensions.index('lat')] 
ids = [ range(0,nlon), range(0,nlat), 5 ] 
ids_permute = [order_want.index(n) for n in nc_fid[var].dimensions] 
ids_query = [l[i] for l,i in zip(ids,ids_permute)] 

sliced_data = nc_fid[var][list_query] 

Это требует не существует априорные знание размерной позиции и не требуют загрузки всех размеров переменной.

Обратите внимание, что после некоторого тестирования %timeit в IPython появляется некоторая специальная задержка для индексирования целых чисел, например. list_query = [0,0,0,0] будет принимать 80 мс тогда как list_query = [range(1),0,0,0] или даже list_query = [[0,1,2,3,4,5],0,0,0] займет 1ms. Очень загадочно; в любом случае, очевидно, вы должны попытаться убедиться, что list_query - это не просто список целых чисел.

Смежные вопросы