这是我第一次使用netCDF,而我正试图用它来处理它。
我有多个版本3 netcdf文件(NOAA NARR air.2m每日平均一年)。每个文件跨越1979年至2012年的一年。它们是349 x 277网格,分辨率约为32千米。数据是从here下载的。
尺寸是时间(自1800年1月1日起的小时数),我感兴趣的变量是空气。我需要计算温度<1的累计天数。 0.例如
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中取得的进展:
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]?
答案 0 :(得分:11)
您可以使用netCDF4中非常好的MFDataset功能将一堆文件视为一个聚合文件,而无需使用ncrcat
。所以你的代码看起来像这样:
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()
这是编写文件的一种方法(可能有更简单的方法):
# 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()
如果我尝试查看the Unidata NetCDF-Java Tools-UI GUI中的结果文件,它似乎没问题: 另请注意,我刚刚下载了两个用于测试的数据集,因此我使用了
f = netCDF4.MFDataset('/usgs/data2/rsignell/models/ncep/narr/air.2m.19??.nc')
作为一个例子。对于所有数据,您可以使用
f = netCDF4.MFDataset('/usgs/data2/rsignell/models/ncep/narr/air.2m.????.nc')
或
f = netCDF4.MFDataset('/usgs/data2/rsignell/models/ncep/narr/air.2m.*.nc')
答案 1 :(得分:4)
这是R
解决方案。
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)
答案 2 :(得分:1)
我知道这个帖子从2013年开始已经很晚了,但我只是想指出,所接受的解决方案并没有为提出的确切问题提供解决方案。这个问题似乎要求每个连续温度低于零的时间长度(如果温度超过零,则计数器重置的问题),这对气候应用(例如农业)很重要,而接受的解决方案只给出总数温度低于零的一年中的天数。如果这真的是mkmitchell想要的(它已被接受为答案)那么它可以从cdo中的命令行完成,而不必担心NETCDF输入/输出:
id
所以循环脚本将是:
cdo timsum -lec,273.15 in.nc out.nc
如果您想要整个期间的总数,那么您可以使用_numdays文件而不是更小:
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
但同样,这个问题似乎需要累积几天每个事件,这是不同的,但不是由接受的答案提供。