Loop through netcdf files and run calculations - Python or R
这是我第一次使用netCDF,我正在努力工作。
我有多个版本3的netcdf文件(一整年的NOAA NARR air.200万日均平均值)。每个文件的时间跨度为1979年至2012年。它们是349 x 277网格,分辨率约为32km。数据是从这里下载的。
维度是时间(自1800年1月1日以来的小时数),我感兴趣的变量是air。我需要计算温度<0的累积天数。例如
1 2 3 4 5 6 | Day 1 = +4 degrees, accumulated days = 0 Day 2 = -1 degrees, accumulated days = 1 Day 3 = -2 degrees, accumulated days = 2 Day 4 = -4 degrees, accumulated days = 3 Day 5 = +2 degrees, accumulated days = 0 Day 6 = -3 degrees, accumulated days = 1 |
我需要将此数据存储在新的netcdf文件中。我对Python有点熟悉,对R也很熟悉。每天循环浏览,检查前几天的值的最佳方法是什么,然后根据此值将值输出到新的netcdf文件,其尺寸和变量完全相同... 。或只是将另一个变量添加到我正在寻找的输出中的原始netcdf文件中。
最好将所有文件分开或合并吗?我将它们与ncrcat结合使用,效果很好,但文件大小为2.3gb。
感谢您的输入。
我目前在python中的进展:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | import numpy import netCDF4 #Change my working DIR f = netCDF4.Dataset('air7912.nc', 'r') for a in f.variables: print(a) #output = lat long x y Lambert_Conformal time time_bnds air f.variables['air'][1, 1, 1] #Output 298.37473 |
为了帮助我更好地理解这一点,我正在使用哪种类型的数据结构?上例中的['air']键是键,[1,1,1]还是键吗?得到298.37473的值。然后如何遍历[1,1,1]?
您可以使用netCDF4中非常好的MFDataset功能将一堆文件视为一个聚合文件,而无需使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | from pylab import * import netCDF4 f = netCDF4.MFDataset('/usgs/data2/rsignell/models/ncep/narr/air.2m.19??.nc') # print variables f.variables.keys() atemp = f.variables['air'] print atemp ntimes, ny, nx = shape(atemp) cold_days = zeros((ny,nx),dtype=int) for i in xrange(ntimes): cold_days += atemp[i,:,:].data-273.15 < 0 pcolormesh(cold_days) colorbar() |
这是一种写入文件的方法(可能有更简单的方法):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | # create NetCDF file nco = netCDF4.Dataset('/usgs/data2/notebook/cold_days.nc','w',clobber=True) nco.createDimension('x',nx) nco.createDimension('y',ny) cold_days_v = nco.createVariable('cold_days', 'i4', ( 'y', 'x')) cold_days_v.units='days' cold_days_v.long_name='total number of days below 0 degC' cold_days_v.grid_mapping = 'Lambert_Conformal' lono = nco.createVariable('lon','f4',('y','x')) lato = nco.createVariable('lat','f4',('y','x')) xo = nco.createVariable('x','f4',('x')) yo = nco.createVariable('y','f4',('y')) lco = nco.createVariable('Lambert_Conformal','i4') # copy all the variable attributes from original file for var in ['lon','lat','x','y','Lambert_Conformal']: for att in f.variables[var].ncattrs(): setattr(nco.variables[var],att,getattr(f.variables[var],att)) # copy variable data for lon,lat,x and y lono[:]=f.variables['lon'][:] lato[:]=f.variables['lat'][:] xo[:]=f.variables['x'][:] yo[:]=f.variables['y'][:] # write the cold_days data cold_days_v[:,:]=cold_days # copy Global attributes from original file for att in f.ncattrs(): setattr(nco,att,getattr(f,att)) nco.Conventions='CF-1.6' nco.close() |
如果我尝试在Unidata NetCDF-Java Tools-UI GUI中查看生成的文件,那似乎还可以:
还要注意,这里我只是下载了两个数据集进行测试,所以我使用了
1 | f = netCDF4.MFDataset('/usgs/data2/rsignell/models/ncep/narr/air.2m.19??.nc') |
举个例子。对于所有数据,您可以使用
1 | f = netCDF4.MFDataset('/usgs/data2/rsignell/models/ncep/narr/air.2m.????.nc') |
要么
1 | f = netCDF4.MFDataset('/usgs/data2/rsignell/models/ncep/narr/air.2m.*.nc') |
这是一个
1 2 3 4 5 6 7 8 9 10 | infiles <- list.files("data", pattern ="nc", full.names = TRUE, include.dirs = TRUE) outfile <-"data/air.colddays.nc" library(raster) r <- raster::stack(infiles) r <- sum((r - 273.15) < 0) plot(r) |
我知道对于从2013年开始的该主题来说,这已经很晚了,但是我只想指出,公认的解决方案并不能为提出的确切问题提供解决方案。问题似乎是希望温度的每个连续周期的长度都低于零(请注意问题,如果温度超过零,计数器将重置),这对于气候应用(例如,对于农业)可能很重要,而公认的解决方案仅给出了总和一年中温度低于零的天数。如果这确实是mkmitchell想要的(已被接受为答案),则可以从cdo的命令行中完成它,而不必担心NETCDF输入/输出:
1 | cdo timsum -lec,273.15 in.nc out.nc |
因此循环脚本将是:
1 2 3 4 5 | files=`ls *.nc` # pick up all the netcdf files in a directory for file in $files ; do # I use 273.15 as from the question seems T is in Kelvin cdo timsum -lec,273.15 $file ${file%???}_numdays.nc done |
如果您想要整个期间的总数,则可以为_numdays文件设置目录,而不是较小的文件:
1 2 | cdo cat *_numdays.nc total.nc cdo timsum total.nc total_below_zero.nc |
但是同样,该问题似乎想要每个事件的累积天数,这是不同的,但不是由公认的答案提供的。