我有一个非常大的netcdf文件,我正在用python中的netcdf4读取它。
我不能一次读取这个文件,因为它的尺寸(1200 x 720 x 1440)太大,整个文件无法同时存储在内存中。第一个维度表示时间,接下来的2个维度分别表示纬度和经度。
import netCDF4
nc_file = netCDF4.Dataset(path_file, 'r', format='NETCDF4')
for yr in years:
nc_file.variables[variable_name][int(yr), :, :]
然而,一次读一年书的速度是极其缓慢的。对于下面的用例,如何加快速度?
--编辑
chunksize是1
我可以读取一系列年份:nc_file.variables[变量名][0:100,:,:]
有几个用例:
年内:
numpy.ma.sum(nc_file.variables[variable_name][int(yr), :, :])
# Multiply each year by a 2D array of shape (720 x 1440)
for yr in years:
numpy.ma.sum(nc_file.variables[variable_name][int(yr), :, :] * arr_2d)
# Add 2 netcdf files together
for yr in years:
numpy.ma.sum(nc_file.variables[variable_name][int(yr), :, :] +
nc_file2.variables[variable_name][int(yr), :, :])
最佳答案
我强烈建议您查看一下xarray
和dask
项目。使用这些强大的工具将允许您轻松地将计算分割成块。这带来了两个好处:您可以根据不适合内存的数据进行计算,并且可以使用机器中的所有核心来获得更好的性能。您可以通过适当地选择块大小来优化性能(请参见)。
您可以通过执行以下简单操作从netcdf加载数据:
import xarray as xr
ds = xr.open_dataset(path_file)
如果要沿时间维度以年为单位划分数据块,则指定
chunks
参数(假定年份坐标名为“year”):ds = xr.open_dataset(path_file, chunks={'year': 10})
由于其他坐标不出现在
chunks
dict中,因此将对它们使用单个块。(请参阅文档documentation中的更多详细信息)。这对于您的第一个需求很有用,因为您每年都要用一个二维数组来相乘。您只需:ds['new_var'] = ds['var_name'] * arr_2d
现在,
xarray
和dask
正在缓慢地计算结果。为了触发实际计算,只需请求xarray
将结果保存回netcdf:ds.to_netcdf(new_file)
计算是通过
dask
触发的,它负责将处理分为若干块,从而能够处理不适合内存的数据。此外,dask
将负责使用所有处理器核心来计算块。xarray
和dask
项目仍然不能很好地处理块在并行计算中“对齐”不好的情况。因为在本例中,我们只在“年”维度中分块,所以我们希望没有问题。如果要将两个不同的netcdf文件添加到一起,其简单程度如下:
ds1 = xr.open_dataset(path_file1, chunks={'year': 10})
ds2 = xr.open_dataset(path_file2, chunks={'year': 10})
(ds1 + ds2).to_netcdf(new_file)
我提供了一个使用here的完整工作示例。
In [1]:
import xarray as xr
import numpy as np
# Load sample data and strip out most of it:
ds = xr.open_dataset('ECMWF_ERA-40_subset.nc', chunks = {'time': 4})
ds.attrs = {}
ds = ds[['latitude', 'longitude', 'time', 'tcw']]
ds
Out[1]:
<xarray.Dataset>
Dimensions: (latitude: 73, longitude: 144, time: 62)
Coordinates:
* latitude (latitude) float32 90.0 87.5 85.0 82.5 80.0 77.5 75.0 72.5 ...
* longitude (longitude) float32 0.0 2.5 5.0 7.5 10.0 12.5 15.0 17.5 20.0 ...
* time (time) datetime64[ns] 2002-07-01T12:00:00 2002-07-01T18:00:00 ...
Data variables:
tcw (time, latitude, longitude) float64 10.15 10.15 10.15 10.15 ...
In [2]:
arr2d = np.ones((73, 144)) * 3.
arr2d.shape
Out[2]:
(73, 144)
In [3]:
myds = ds
myds['new_var'] = ds['tcw'] * arr2d
In [4]:
myds
Out[4]:
<xarray.Dataset>
Dimensions: (latitude: 73, longitude: 144, time: 62)
Coordinates:
* latitude (latitude) float32 90.0 87.5 85.0 82.5 80.0 77.5 75.0 72.5 ...
* longitude (longitude) float32 0.0 2.5 5.0 7.5 10.0 12.5 15.0 17.5 20.0 ...
* time (time) datetime64[ns] 2002-07-01T12:00:00 2002-07-01T18:00:00 ...
Data variables:
tcw (time, latitude, longitude) float64 10.15 10.15 10.15 10.15 ...
new_var (time, latitude, longitude) float64 30.46 30.46 30.46 30.46 ...
In [5]:
myds.to_netcdf('myds.nc')
xr.open_dataset('myds.nc')
Out[5]:
<xarray.Dataset>
Dimensions: (latitude: 73, longitude: 144, time: 62)
Coordinates:
* latitude (latitude) float32 90.0 87.5 85.0 82.5 80.0 77.5 75.0 72.5 ...
* longitude (longitude) float32 0.0 2.5 5.0 7.5 10.0 12.5 15.0 17.5 20.0 ...
* time (time) datetime64[ns] 2002-07-01T12:00:00 2002-07-01T18:00:00 ...
Data variables:
tcw (time, latitude, longitude) float64 10.15 10.15 10.15 10.15 ...
new_var (time, latitude, longitude) float64 30.46 30.46 30.46 30.46 ...
In [6]:
(myds + myds).to_netcdf('myds2.nc')
xr.open_dataset('myds2.nc')
Out[6]:
<xarray.Dataset>
Dimensions: (latitude: 73, longitude: 144, time: 62)
Coordinates:
* time (time) datetime64[ns] 2002-07-01T12:00:00 2002-07-01T18:00:00 ...
* latitude (latitude) float32 90.0 87.5 85.0 82.5 80.0 77.5 75.0 72.5 ...
* longitude (longitude) float32 0.0 2.5 5.0 7.5 10.0 12.5 15.0 17.5 20.0 ...
Data variables:
tcw (time, latitude, longitude) float64 20.31 20.31 20.31 20.31 ...
new_var (time, latitude, longitude) float64 60.92 60.92 60.92 60.92 ...
关于python - 加快阅读python中非常大的netcdf文件,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/35422862/