python netcdf: создание копии всех переменных и атрибутов, кроме одного

Мне нужно обработать одну переменную в файле netcdf, который фактически содержит много атрибутов и переменных. Я думаю, что невозможно обновить файл netcdf (см. вопрос Как удалить переменную в Scientific.ИО.NetCDF.NetCDFFile?)

мой подход следующий:

  1. сделать переменную для обработки из исходного файла
  2. переменная
  3. скопируйте все данные из исходного netcdf, но обработанные переменная для конечного файла
  4. скопируйте обработанную переменную в конечный файл

моя проблема заключается в том, чтобы кодировать Шаг 3. Я начал со следующего:--4-->

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

Как я могу сохранить все данные и атрибут в полном коде без необходимости перестраивать всю структуру данных?

5 ответов


вот что я только что использовал и работал. ответ @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__)

если вы просто хотите скопировать файл выбираем переменные, nccopy - отличный инструмент, представленный @rewfuss.

вот для Python (и более гибкие) решения с python-netcdf4. Это позволяет открыть его для обработки и других вычислений перед записью в файл.

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, или если вы вызываете .close() на Dataset.

конечно, если вы хотите обработать переменные перед их написанием, вы должны быть осторожны с тем, какие измерения создавать. В новом файле никогда не записывайте переменные без их создания. Кроме того, никогда не создавайте переменные без определенных измерений, как отметил в python-netcdf4's документация.


утилита nccopy в C netCDF версии 4.3.0 и более поздних версиях включает в себя возможность перечислить, какие переменные должны быть скопированы (вместе с их атрибутами). К сожалению, он не включает опцию, для которой переменные следует исключить, что вам и нужно.

однако, если список (разделенных запятыми) переменных, которые должны быть включены, не заставляет командную строку nccopy превышать системные ограничения, это будет работать. Существует два варианта этой опции:

nccopy -v var1,var2,...,varn input.nc output.nc
nccopy -V var1,var2,...,varn input.nc output.nc

в первый (-V) включает все определения переменных, но только данные для именованных переменных. Второй (- V)не включает определения или данные для неназванных переменных.


этот ответ основан на ответе Ксавье Хо (https://stackoverflow.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][:]

Я знаю, это старый вопрос, но в качестве альтернативы, вы можете использовать библиотеку в формате 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