Python:使用netCDF4替换netcdf文件中的值

9

我有一个包含多个小于0的值的netcdf文件。我想将它们全部替换为单个值(比如-1)。我该如何使用netCDF4实现这一点?我是这样读取文件的:

import netCDF4

dset      = netCDF4.Dataset('test.nc')
dset[dset.variables['var'] < 0] = -1
4个回答

14

如果您想保留netCDF变量对象中的数据,则应该使用以下方法:

import netCDF4

dset = netCDF4.Dataset('test.nc', 'r+')

dset['var'][:][dset['var'][:] < 0] = -1

dset.close() # if you want to write the variable back to disk

如果您不想将数据写回磁盘,请直接获取numpy数组并进行切片/赋值:

data = dset['sea_ice_cover'][:]  # data is a numpy array
data[data < 0] = -1

1
如果变量使用scale_factor和add_offset进行压缩,请注意。在这种情况下,只有fill_value属性指定的值将直接写入文件。任何其他值都将自动压缩。 - sfinkens

9

对我而言,前面的回答并不可行,我用以下方法解决:

dset = netCDF4.Dataset('test.nc','r+')
dset.variables['var'][:]
... your changes ...
dset.close() 

“...你的更改...”可能需要更详细的说明。在我看来,这个答案相当不完整,也不是很有用。 - Bernd Wechner

5

解决方案1:Python xarray

该解决方案使用xarray读取和写入netcdf文件,并使用该软件包的函数where来有条件地重置值。

import xarray as xr
ds=xr.open_dataset('test.nc')
ds['var']=xr.where((ds['var']<0),-1,ds['var'])
ds.to_netcdf('modified_test.nc') # rewrite to netcdf

解决方案2:使用命令行中的NCO

我知道原帖想要一个Python解决方案,但如果有人只想从命令行快速执行此任务,则也可以使用NCO进行操作:

ncap2 -s 'where(x<0.) x=-1;' input.nc -O output.nc

根据此帖子:将netcdf文件中低于某个阈值的值设置为该阈值

解决方案3:使用CDO命令行

cdo还具有表达式功能,可以让您在命令行中一行代码解决此问题。

cdo -expr,'var = ((var < 0)) ? -1 : var' infile.nc outfile.nc

Python中有一个 cdo 软件包,可让您直接在Python中使用此功能,而无需使用 sys 。


1
这是一个不错的解决方案!有没有涉及xarray的解决方案,可以不重写文件,而只是更新更改的值? - elbOlita
@elbOlita 当然,只需省略ds.to_netcdf命令即可... - ClimateUnboxed

0
为了能够使用方程进行条件计算,而不仅仅是使用常数计算,我已经根据@jhamman的代码,包含了一个基于变量的条件迭代,该变量形状为(month,lats,lons):
import netCDF4 as nc
import numpy as np
import time

Tmin = -1.7
Tmax = 4.9
perc = (Tmax-Tmin)/100

lats = np.arange(0,384,1)
lons = np.arange(0,768,1)
months = [0,1]
dset = nc.Dataset('path/file.nc', 'r+')

start = time.time()
dset['var'][:][dset['var'][:] < Tmin] = 100
step1 = time.time()
print('Step1 took: ' + str(step1-start))
dset['var'][:][dset['var'][:] > Tmax] = 0
step2 = time.time()
print('Step2 took: ' + str(step2 - step1))

#start iteration of each dimension to alter individual values according to equation new_value = 100-((Old_value +1.8)/1%)
for m in months:
    newstart = time.time()
    for i in lats:
        step3 = time.time()
        print('month lats lat layer '+str(i)+' took: '+str(step3-newstart) +'s')
        for j in lons:
            if dset['var'][m,i,j] < Tmax and dset['var'][m,i,j] > Tmin:
                dset['var'][m,i,j] = 100-((dset['var'][m,i,j]+1.8)/perc)       

     end = time.time()
     print('One full month took: ' + str(end-start) +'s')  

dset.close() 

问题在于它变成了非常慢的代码。
Step1 took: 0.0343s
Step2 took: 0.0253s
month lats lat layer: 0.4064s
One full month took 250.8082s

这是由于迭代逻辑导致的。不过我想知道你们中是否有人有加速这个过程的想法。这些迭代对于实现这个目标真的必要吗?


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接