循环遍历 netcdf 文件并运行计算 - Python 或 R

Posted

技术标签:

【中文标题】循环遍历 netcdf 文件并运行计算 - Python 或 R【英文标题】:Loop through netcdf files and run calculations - Python or R 【发布时间】:2013-09-10 23:38:26 【问题描述】:

这是我第一次使用 netCDF,我正在努力使用它。

我有多个版本 3 netcdf 文件(NOAA NARR air.2m 全年平均每天)。每个文件跨越 1979 年至 2012 年之间的一年。它们是 349 x 277 网格,分辨率约为 32 公里。数据是从here下载的。

维度是时间(自 1800 年 1 月 1 日以来的小时数),我感兴趣的变量是空气。我需要计算温度

    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]?

【问题讨论】:

我知道这对于 2013 年的这个线程来说已经相当晚了,但我只是想指出,接受的解决方案并没有为所提出的问题提供解决方案。这个问题似乎想要温度低于零的每个连续周期的长度(请注意,如果温度超过零,计数器会重置),而这个解决方案只给出一年中温度低于零的总天数。这不是细微的差别。如果只需要总天数,则应编辑问题以说明这一点。 【参考方案1】:

我知道这对于 2013 年的这个线程来说已经相当晚了,但我只想指出,接受的解决方案并没有为所提出的确切问题提供解决方案。问题似乎需要温度低于零的每个连续周期的长度(请注意,如果温度超过零,计数器将重置),这对于气候应用(例如农业)可能很重要,而公认的解决方案仅给出总数一年中气温低于零的天数。如果这确实是 mkmitchell 想要的(它已被接受为答案),那么它可以在 cdo 的命令行中完成,而不必担心 NETCDF 输入/输出:

 cdo timsum -lec,273.15 in.nc out.nc

所以循环脚本是:

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 文件来代替它们:

cdo cat *_numdays.nc total.nc 
cdo timsum total.nc total_below_zero.nc 

但同样,问题似乎需要累积天数每个事件,这是不同的,但不是由接受的答案提供。

【讨论】:

【参考方案2】:

这是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)

【讨论】:

【参考方案3】:

您可以使用 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')

【讨论】:

谢谢先生!这正是我一直在寻找的,而且比我预期的要深入得多。你为我节省了很多时间。我总是对社区印象深刻。 我已经在另一个线程上提到了这一点,但令人遗憾的是,MFDataset 不适用于 python 中的 NetCDF4,即使有一些限制。有很多 MFDataset 使用的好例子,这些对许多遗留文件都有好处,但对最新标准却没有。 我在上面发表评论说明这​​个解决方案(虽然优雅而详细)没有回答提出的问题,因为它提供了一年中低于零的总天数,而不是每个连续的长度低于冰点的时期,这对农业来说可能很重要。

以上是关于循环遍历 netcdf 文件并运行计算 - Python 或 R的主要内容,如果未能解决你的问题,请参考以下文章

创建一个循环来读取excel文件 - python

使用 shapefile 屏蔽 NetCDF 并计算 shapefile 中所有多边形的平均值和异常值

循环遍历文本文件中的 SQL 查询并执行 - pyodbc

python第四周程序控制之循环,randow库,圆周率的计算

使用for循环遍历100以内的奇数,并计算所有的奇数的和并输出?

有没有办法计算和保存一个新变量,它是多个 netCDF 或 tif 文件的函数?