由于初学Python,处理数据时老是被fortran的固有思维束缚:比如python对于nc文件的处理十分简单(尤其是对于数据量非常大的长时间序列),但由于习惯fortran循环批量处理数据文件导致下载nc文件时将不同年份的数据单独放在不同nc文件里。导致后续处理十分麻烦(卡死),后学习python的文件读取后发现非常简单。故总结如下:
<一> 批量处理过程:
在下载ERA5数据时API非常方便,但API将数据都存在一个nc文件里。简单利用for循环+数据类型强制转换实现将不同年份的数据存在不同nc文件里:
import cdsapi
c = cdsapi.Client()
for i in range(62):
k = 1960 + i
print(k)
c.retrieve(
'reanalysis-era5-land-monthly-means',
{
'format': 'netcdf',
'product_type': 'monthly_averaged_reanalysis',
'variable': '2m_temperature',
'year': k,
'month': [
'01', '02', '03',
'04', '05', '06',
'07', '08', '09',
'10', '11', '12',
],
'time': '00:00',
},
str(k)+'.nc')
处理时利用netCDF4库进行文件读取(一个为例,但需要循环62次—直接GG):
# 读取nc数据
import netCDF4 as nc
import numpy as np
count = 1960
file = r'D:\\fang\\aniconda\\python program\\' +str(count)+ '.nc'
dataset = nc.Dataset(file)
t2_3 = dataset.variables['t2m'][2].data
t2_8 = dataset.variables['t2m'][7].data
t2_3 = np.array(t2_3)
t2_8 = np.array(t2_8)
后来发现xarray中有open_mfdataset()函数可以读取多个文件——相当于逐个读取后再利用concat函数将各个文件中数据合并为单个Dataset对象。
利用open_mfdataset读取如下:发现读取后为DataArray对象(变量类型为dask.array,Dask是专门用于处理外存(out-of-core)运算的数组类型,用于处理无法直接加载到计算机内存的大型数据)。
import xarray as xr
mf = xr.open_mfdataset('D:\\fang\\data\\t2m\\*.nc')['t2m'][2: :12, :, :]
print(mf)
dask.array
Coordinates:
* longitude (longitude) float32 0.0 0.1 0.2 0.3 ... 359.6 359.7 359.8 359.9
* latitude (latitude) float32 90.0 89.9 89.8 89.7 ... -89.8 -89.9 -90.0
* time (time) datetime64[ns] 1960-03-01 1961-03-01 ... 2021-03-01
Attributes:
units: K
long_name: 2 metre temperature
<二>整体处理
发现批量处理实现比较麻烦时,遂将多年资料下载至一个nc文件里,利用xarray.open_dataset()读取:下面是netCDF4与xarray读取方式:
import xarray as xr
import netCDF4 as nc
t2 = nc.Dataset('D:\\fang\\aniconda\\python program\\download.nc')
t2_data = t2.variables['t2m'][2: :12, :, :]
t2_3 = xr.open_dataset('D:\\fang\\aniconda\\python program\\download.nc')['t2m'][2: :12, :, :]
print(type(t2_data))
print(type(t2_3), t2)
运行结果如下:
root group (NETCDF3_64BIT_OFFSET data model, file format NETCDF3):
Conventions: CF-1.6
history: 2022-09-24 06:39:01 GMT by grib_to_netcdf-2.25.1: /opt/ecmwf/mars-client/bin/grib_to_netcdf.bin -S param -o /cache/data9/adaptor.mars.internal-1664001370.1249135-11101-7-6fdb6850-689b-4d8b-90d5-8cae6deedf2d.nc /cache/tmp/6fdb6850-689b-4d8b-90d5-8cae6deedf2d-adaptor.mars.internal-1664001144.3804803-11101-12-tmp.grib
dimensions(sizes): longitude(3600), latitude(1801), time(744)
variables(dimensions): float32 longitude(longitude), float32 latitude(latitude), int32 time(time), int16 t2m(time, latitude, longitude)
groups:
Process finished with exit code 0
发现利用nc.Dataset读取后的nc文件存储为一个Dataset对象(t2),而其变量数值(t2_data)则为MaskdArray对象,可以用来进行numpy的计算以及函数操作;直接用xarray.open_dataset()读取后也为Dataset对象(代码略),读取部分的话为DataArray(t2_3), 则需要进行转换(t2_3 = t2_3.values[])才能用于numpy计算。
深刻体会到学python必须摈弃向量循环操作,注重函数与库的灵活使用。(PS:python真的好用)