Как связать функцию с конкретным файлом netCDF на основе отметки времени

У меня есть 73 файла netCDF, каждый из которых представляет 5-дневные интервалы календарного года и имеет несколько переменных. Каждый файл состоит из 120 слоев, представляющих часовые интервалы.

Я прочитал их все в R и назвал их соответствующим образом, используя пакет ncdf4, например:

filenames <- list.files(path=getwd()) 

for(i in filenames) {
  ncin <- nc_open(i)
  ds<-paste(i)
  assign(ds, ncin)
  print(i)
  }

У меня также есть фрейм данных с местоположениями в той же проекции, что и файлы netCDF (широта и долгота), однако эти местоположения также нерегулярно охватывают весь календарный год. Пример данных выглядит так:

>head(df)
> Lon      Lat            datetime
2 -3.179046 58.65417 2016-09-30 17:25:38
3 -3.180403 58.65483 2016-09-30 17:29:43
4 -3.187734 58.66102 2016-09-30 21:22:51
5 -3.190197 58.66409 2016-09-30 22:02:47
6 -3.182058 58.67433 2016-10-01 06:16:08
7 -3.181318 58.67475 2016-10-01 06:20:31

Что я пытаюсь сделать, так это сопоставить фрейм данных с правильным файлом netCDF и слоем на основе его отметки даты и времени, т.е. если это между 1 и 5 днями года, это будет файл netCDF 1 и т. Д., Тогда я хочу интерполировать переменные данные из файла netCDF в данные о местоположении с соответствующей меткой даты и времени кадра данных. Итак, каково значение переменной V в тот же день и время в файле netCDF в заданное время и в указанном кадре данных. Я могу выполнить первую часть, используя функции цикла, но это крайне неэффективно и требует много времени для кодирования:

function(dataframe){
d <- dataframe[i,]
if(between(d$datetime, 2017-01-01 00:00:00, 2017-01-05 23:59:59){ncfile <- file1} else if (between(d$datetime, 2017-01-06 00:00:00, 2017-01-010 23:59:59)) 
     {ncfile <- file2}}

И так далее ... Я никогда раньше не работал с файлами netCDF, я не уверен в лучшем методе. Какие-либо предложения?

################# UPDATE

Я читал файлы netCDF при использовании

filenames <- list.files(path=getwd()) 
x <- lapply(filenames, nc_open)

извлекать из файла даты с последовательными именами:

PFOW_Climatology2_0001_1993-01-01.nc
PFOW_Climatology2_0002_1993-01-06.nc

up to

PFOW_Climatology2_0073_1993-12-27.nc

используя

fd <- as.Date(substr(filenames, 24, 36))

Затем я создаю справочный столбец для фрейма данных, находя интервал, в котором каждая точка данных соответствует в fd, следующим образом:

i <- findInterval(dd, fd) 
df$file <- i

person Jojo    schedule 15.11.2017    source источник


Ответы (1)


Очень сложно дать хороший ответ, не предоставив дополнительную информацию, а в идеале - несколько примеров данных.

Ваше «подходящее наименование» совершенно неуместно. Вы действительно не должны нуждаться в assign в повседневной жизни. Просто составьте список.

library(ncdf4)
x <- lapply(filenames, nc_open)

Но поскольку вам нужно извлекать значения по местоположению, возможно, лучше составить список объектов RasterBrick:

library(raster)
x <- lapply(filenames, brick)

Но я бы тоже не стал этого делать.

Я бы сначала сопоставил имена файлов с df $ datetime. Поскольку вы не говорите нам, как выглядят имена файлов, я не могу сказать вам, как это сделать. Но петля вам не понадобится. Извлеките даты из имен файлов, создайте соответствующий объект даты (и времени?) И выполните что-то вроде

fd <- as.Date(subtr(filenames, 4, 12))
dd <- as.Date(df$datetime)
i <- which(dd > fd[-length(fd)] & dd < fd[-1]) + 1 

df$file <- filenames[i]
df$id <- 1:nrow(df)

Теперь вы можете перебирать имена файлов и извлекать значения:

ff <- unique(df$file)
vv <- sapply(ff, function(f) {
         v <- extract(brick(f), df[df$file == f , c('lon', 'lat')])
         data.frame(file=f, xy, v)
      })

vv должен быть data.frame со значениями для каждого случая для соответствующего 5-дневного интервала. Оттуда выберите (или интерполируйте) желаемое время из 120 значений.

Я предполагаю, что вы хотите сделать временную интерполяцию. Для (также) пространственной интерполяции используйте method = 'bilinear' в extract

Опять же, это может не сработать, так как у меня нет данных для примера. Но что-то в этом роде сработает.

person Robert Hijmans    schedule 16.11.2017
comment
Спасибо @RobertH. Я изменил вопрос, чтобы включить дополнительную информацию, и обновил его, включив в него самые последние сделанные вами предложения, которые были очень полезны. Мне не удалось заставить вашу функцию {which} работать, поэтому я использовал вместо нее findInterval. - person Jojo; 16.11.2017
comment
Однако я не уверен, как должна работать ваша функция. Если вы попытаетесь заблокировать объект ncdf4, вы получите сообщение об ошибке: «не удалось найти унаследованный метод для функции« растр »для сигнатуры« ncdf4 » - person Jojo; 16.11.2017
comment
brick следует использовать в имени файла, а не в объекте ncdf4 - person Robert Hijmans; 17.11.2017