python netcdf:复制所有变量和属性,但一个
Posted
技术标签:
【中文标题】python netcdf:复制所有变量和属性,但一个【英文标题】:python netcdf: making a copy of all variables and attributes but one 【发布时间】:2013-02-14 23:59:39 【问题描述】:我需要处理 netcdf 文件中的单个变量,该文件实际上包含许多属性和变量。 我认为无法更新 netcdf 文件(请参阅问题 How to delete a variable in a Scientific.IO.NetCDF.NetCDFFile?)
我的方法如下:
-
从原始文件中获取要处理的变量
处理变量
将所有数据从原始 netcdf 但处理后的变量复制到最终文件
将处理后的变量复制到最终文件中
我的问题是编写第 3 步的代码。我从以下内容开始:
def processing(infile, variable, outfile):
data = fileH.variables[variable][:]
# do processing on data...
# and now save the result
fileH = NetCDFFile(infile, mode="r")
outfile = NetCDFFile(outfile, mode='w')
# build a list of variables without the processed variable
listOfVariables = list( itertools.ifilter( lamdba x:x!=variable , fileH.variables.keys() ) )
for ivar in listOfVariables:
# here I need to write each variable and each attribute
如何在少量代码中保存所有数据和属性,而无需重建整个数据结构?
【问题讨论】:
【参考方案1】:这是我刚刚使用和工作的内容。 @arne 的答案已针对 Python 3 进行了更新,还包括复制变量属性:
import netCDF4 as nc
toexclude = ['ExcludeVar1', 'ExcludeVar2']
with netCDF4.Dataset("in.nc") as src, netCDF4.Dataset("out.nc", "w") as dst:
# copy global attributes all at once via dictionary
dst.setncatts(src.__dict__)
# copy dimensions
for name, dimension in src.dimensions.items():
dst.createDimension(
name, (len(dimension) if not dimension.isunlimited() else None))
# copy all file data except for the excluded
for name, variable in src.variables.items():
if name not in toexclude:
x = dst.createVariable(name, variable.datatype, variable.dimensions)
dst[name][:] = src[name][:]
# copy variable attributes all at once via dictionary
dst[name].setncatts(src[name].__dict__)
【讨论】:
从 netCDF4 开始,您必须在设置数据之前定义任何填充值,否则您可能会得到AttributeError
。因此,最好将属性写在数据之前(即交换最后两行的顺序:dst[name][:] = src[name][:]
和dst[name].setncatts(src[name].__dict__)
。【参考方案2】:
如果您只是想复制文件来挑选变量,@rewfuss 提交的nccopy
是一个很棒的工具。
这是一个带有python-netcdf4
的 Pythonic(更灵活)解决方案。这允许您在写入文件之前打开它以进行处理和其他计算。
with netCDF4.Dataset(file1) as src, netCDF4.Dataset(file2) as dst:
for name, dimension in src.dimensions.iteritems():
dst.createDimension(name, len(dimension) if not dimension.isunlimited() else None)
for name, variable in src.variables.iteritems():
# take out the variable you don't want
if name == 'some_variable':
continue
x = dst.createVariable(name, variable.datatype, variable.dimensions)
dst.variables[x][:] = src.variables[x][:]
这不考虑变量属性,例如fill_values
。您可以按照文档轻松完成。
请注意,netCDF4 文件一旦以这种方式写入/创建,将无法撤消。修改变量的那一刻,它会在 with 语句的末尾写入文件,或者如果您在 Dataset
上调用 .close()
。
当然,如果您希望在编写变量之前对其进行处理,则必须注意要创建哪些维度。在新文件中,切勿在未创建变量的情况下写入变量。此外,切勿在没有定义维度的情况下创建变量,例如 noted in python-netcdf4
's documentation。
【讨论】:
这个问题的解决方案非常好,但是在我可以让它工作之前有一些修复。首先是“.iteritems()”不再适用于 3.x,需要更改为“.items()”。其次是将 x 的使用替换为变量的字符串,例如 'dst.variables[name][:] = src.variables[name][:]'。【参考方案3】:这个答案建立在 Xavier Ho (https://***.com/a/32002401/7666) 的答案之上,但我需要修复它来完成它:
import netCDF4 as nc
import numpy as np
toexclude = ["TO_REMOVE"]
with nc.Dataset("orig.nc") as src, nc.Dataset("filtered.nc", "w") as dst:
# copy attributes
for name in src.ncattrs():
dst.setncattr(name, src.getncattr(name))
# copy dimensions
for name, dimension in src.dimensions.iteritems():
dst.createDimension(
name, (len(dimension) if not dimension.isunlimited else None))
# copy all file data except for the excluded
for name, variable in src.variables.iteritems():
if name not in toexclude:
x = dst.createVariable(name, variable.datatype, variable.dimensions)
dst.variables[name][:] = src.variables[name][:]
【讨论】:
isunlimited
现在似乎是一个函数 (isunlimited()
)【参考方案4】:
C netCDF 4.3.0 及更高版本中的 nccopy 实用程序包括一个选项,用于列出要复制的变量(及其属性)。不幸的是,它不包括排除哪些变量的选项,这是您需要的。
但是,如果要包含的(以逗号分隔的)变量列表不会导致 nccopy 命令行超出系统限制,那么这将起作用。此选项有两种变体:
nccopy -v var1,var2,...,varn input.nc output.nc
nccopy -V var1,var2,...,varn input.nc output.nc
第一个 (-v) 包括所有变量定义,但仅包含命名变量的数据。 第二个 (-V) 不包括未命名变量的定义或数据。
【讨论】:
【参考方案5】:我知道这是一个老问题,但作为替代方案,您可以使用库 netcdf 和 shutil:
import shutil
from netcdf import netcdf as nc
def processing(infile, variable, outfile):
shutil.copyfile(infile, outfile)
with nc.loader(infile) as in_root, nc.loader(outfile) as out_root:
data = nc.getvar(in_root, variable)
# do your processing with data and save them as memory "values"...
values = data[:] * 3
new_var = nc.getvar(out_root, variable, source=data)
new_var[:] = values
【讨论】:
嗨@ecolell,我知道这是一个较旧的回复。与此同时,我们使用 netCDF4 并且似乎没有包含“加载器”类。你知道如何用 netCDF4 应用这段代码吗? @Linda 我在这个库上不活跃,但我刚刚上传了该库最新版本的副本。在以下链接中,您将找到代码:github.com/ecolell/netcdf/blob/…(希望对您有所帮助)。以上是关于python netcdf:复制所有变量和属性,但一个的主要内容,如果未能解决你的问题,请参考以下文章