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

Python 按维度名称提取netcdf4变量切片,python,netcdf,Python,Netcdf,我有一个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。如何按维度名称而不是位置进行访问?您可以使用的索引功能按维度名称访问netcdf数据

我有一个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
。如何按维度名称而不是位置进行访问?

您可以使用的索引功能按维度名称访问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))
您可以使用的索引功能按维度名称访问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))

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

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

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

在Ipython中使用
%timeit
进行测试,确认了正常切片和
np.take
方法之间的主要差异


希望有人能给出一个更完整的答案;对于不同的数据集非常有用

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

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

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

在Ipython中使用
%timeit
进行测试,确认了正常切片和
np.take
方法之间的主要差异


希望有人能给出一个更完整的答案;对于不同的数据集非常有用

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

numpy数组显然可以用一个iterables的单例列表进行索引,例如

a = np.reshape(range(0,16),(4,4),order='F')
a = a[ [[0,1], [1]] ]
返回
a
等于
数组([4,5])
。另一个例子是
[[range(3),[12],3]]
。这些单例列表以
*下标的方式展开,就好像您直接查询了
a[[0,1],1]
而不是
a[[0,1],1]

因此,如果您能够查询netCDF变量中每个维度的位置和长度(使用
nc_fid[var].dimension
nc_fid[var].shape非常简单),那么您可以根据每个维度的位置简单地排列一个列表。例如,如果您有按lon按lat计算的形状时间数据,并且您想要所有经度,所有经度,以及时间索引
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\u query=[0,0,0]
将花费80ms
list\u query=[range(1),0,0,0]
甚至
list\u query=[0,1,2,3,4,5],0,0]
将花费1ms。非常神秘;无论如何,显然你应该确保
list\u query
不仅仅是一个整数列表。

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

numpy数组显然可以用一个iterables的单例列表进行索引,例如

a = np.reshape(range(0,16),(4,4),order='F')
a = a[ [[0,1], [1]] ]
返回
a
等于
数组([4,5])
。另一个例子是
[[range(3),[12],3]]
。这些单例列表以
*下标的方式展开,就好像您直接查询了
a[[0,1],1]
而不是
a[[0,1],1]

因此,如果您能够查询netCDF变量中每个维度的位置和长度(使用
nc_fid[var].dimension
nc_fid[var].shape非常简单),那么您可以根据每个维度的位置简单地排列一个列表。例如,如果您有按lon按lat计算的形状时间数据,并且您想要所有经度,所有经度,以及时间索引
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\u query=[0,0,0]
将花费80ms
list\u query=[range(1),0,0,0]
甚至
list\u query=[0,1,2,3,4,5],0,0]
将花费1ms。非常神秘;无论如何,显然您应该确保
list\u query
不仅仅是一个整数列表