Python学习记录 ——文件处理(xarray与netCDF)

 由于初学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')

下载后: (1960-2021)Python学习记录 ——文件处理(xarray与netCDF)_第1张图片

处理时利用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真的好用)

你可能感兴趣的:(学习,python)