按维度名称提取netcdf4变量切片

问题描述 投票:0回答:3

我有一个 4 维的 netCDF 文件。我想通过给出其中一个维度的名称来从 netCDF 文件中提取切片

我知道如何按位置执行此操作。例如

from netCDF4 import Dataset
hndl_nc = Dataset(path_to_nc)

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

鉴于我知道尺寸的名称,请说

A
B
C
D
。如何通过维度名称而不是位置进行访问?

python netcdf
3个回答
3
投票

您可以使用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))

0
投票

所以,我可能想出了一些可以称为“解决方案”的东西。

numpy 数组显然可以使用可迭代的单例列表进行索引,例如

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
非常简单),那么您可以简单地根据每个维度的位置排列列表。例如,如果您有按 lon 按 lat 的形状时间数据,并且需要 all 经度、all 纬度和时间索引
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]

这不需要尺寸位置的先验知识,并且不需要需要加载变量的所有尺寸。

请注意,在 IPython 中进行一些

%timeit
测试后,似乎全整数索引存在一些特殊的延迟,例如
list_query = [0,0,0,0]
将需要 80ms,而
list_query = [range(1),0,0,0]
甚至
list_query = [[0,1,2,3,4,5],0,0,0]
将需要 1ms。非常神秘;无论如何,显然你应该尝试确保
list_query
不仅仅是一个整数列表。


0
投票

目前最接近的解决方案似乎是

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

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

其中

dim_ids
是切片的列表或元组,
dim
是要沿其切片的维度。不幸的是,这似乎首先加载整个数据集,并且似乎没有办法解决这个问题;
[:]
是必要的。在第一种方法中忽略它会加载数据,而无需从
add_offset
_FillValue
等参数进行调整;在第二种方法中忽略它会产生错误。

在 ipython 中使用

%timeit
进行测试,证实了正常切片和
np.take
方法之间的主要差异。

希望有人对此提出更完整的答案;对于不同的数据集非常有用。

© www.soinside.com 2019 - 2024. All rights reserved.