我强烈建议你查看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
字典中,因此它们将使用单个数据块。(更多细节请参见文档这里。) 这对于您的第一个需求非常有用,您希望将每年乘以一个 2D 数组。您只需执行以下操作:
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)
我提供了一个使用在线可用数据集的完全可工作示例。
In [1]:
import xarray as xr
import numpy as np
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 ...
[1997:2007,:,:]
? - hpaulj